bump version to 6.1 am: 4afca79c73 am: 9224755e53 am: f4c84a49b9

Original change: https://android-review.googlesource.com/c/platform/external/ethtool/+/2804541

Change-Id: I1a77d6e472fcac4e9cf5621cbfbd639b866dbc9f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index 181beb4..54e04d3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -57,9 +57,9 @@
         "-Wno-gnu-variable-sized-type-not-at-end",
         "-Wno-unused-parameter",
         "-DETHTOOL_ENABLE_NETLINK",
-        "-DETHTOOL_ENABLE_PRETTY_DUMP",
+        // causes a fair bit of binary bloat: "-DETHTOOL_ENABLE_PRETTY_DUMP",
         "-DPACKAGE=\"ethtool\"",
-        "-DVERSION=\"6.1\"",
+        "-DVERSION=\"6.5\"",
     ],
     apex_available: [
         "com.android.tethering",
diff --git a/Makefile.am b/Makefile.am
index 663f40a..ae3b667 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,7 +7,8 @@
 
 sbin_PROGRAMS = ethtool
 ethtool_SOURCES = ethtool.c uapi/linux/ethtool.h internal.h \
-		  uapi/linux/net_tstamp.h rxclass.c common.c common.h \
+		  uapi/linux/net_tstamp.h uapi/linux/if.h uapi/linux/hdlc/ioctl.h \
+		  rxclass.c common.c common.h \
 		  json_writer.c json_writer.h json_print.c json_print.h \
 		  list.h
 if ETHTOOL_ENABLE_PRETTY_DUMP
@@ -18,7 +19,7 @@
 		  smsc911x.c at76c50x-usb.c sfc.c stmmac.c	\
 		  sff-common.c sff-common.h sfpid.c sfpdiag.c	\
 		  ixgbevf.c tse.c vmxnet3.c qsfp.c qsfp.h fjes.c lan78xx.c \
-		  igc.c cmis.c cmis.h bnxt.c cpsw.c lan743x.c
+		  igc.c cmis.c cmis.h bnxt.c cpsw.c lan743x.c hns3.c
 endif
 
 if ENABLE_BASH_COMPLETION
@@ -37,13 +38,16 @@
 		  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/module-eeprom.c netlink/module.c netlink/rss.c \
 		  netlink/desc-rtnl.c netlink/cable_test.c netlink/tunnels.c \
+		  netlink/plca.c \
+		  netlink/pse-pd.c \
 		  uapi/linux/ethtool_netlink.h \
 		  uapi/linux/netlink.h uapi/linux/genetlink.h \
-		  uapi/linux/rtnetlink.h uapi/linux/if_link.h
+		  uapi/linux/rtnetlink.h uapi/linux/if_link.h \
+		  uapi/linux/if.h uapi/linux/hdlc/ioctl.h
 AM_CPPFLAGS += @MNL_CFLAGS@
 LDADD += @MNL_LIBS@
 endif
diff --git a/NEWS b/NEWS
index 5687c69..e5eca95 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,38 @@
+Version 6.5 - September 12, 2023
+	* Feature: register dump for hns3 driver (-d)
+	* Fix: fix fallback to ioctl for sset (-s)
+	* Fix: fix empty slot search in rmgr (-N)
+
+Version 6.4 - July 1, 2023
+	* Feature: get/set Tx push buffer length (-G)
+	* Feature: sff-8636 and cmis: report LOL / LOS / Tx Fault (-m)
+	* Fix: fix duplex setting parser (-s)
+	* Misc: check and require C11 language standard
+	* Misc: clean up obsolete pre-build checks
+
+Version 6.3 - May 8, 2023
+	* Feature: PLCA support (--[gs]et-plca-cfg, --get-plca-status)
+	* Feature: MAC Merge layer support (--show-mm, --set-mm)
+	* Feature: pass source of statistics for port stats
+	* Feature: get/set rx push in ringparams (-g and -G)
+	* Feature: coalesce tx aggregation parameters (-c and -C)
+	* Feature: PSE and PD devices (--show-pse, --set-pse)
+	* Fix: minor fixes of help text (--help)
+	* Fix: fix build on systems with older system headers
+	* Fix: fix netlink support when PLCA is not present (no option)
+	* Fix: fixes for issues found with gcc13 -fanalyzer
+	* Fix: fix return code in rxclass_rule_ins (-N)
+	* Fix: more robust argc/argv handling
+
+Version 6.2 - February 21, 2023
+	* Feature: link down event statistics (no option)
+	* Feature: JSON output for coalesce (-c)
+	* Feature: new link modes (no option)
+	* Feature: JSON output for ring (-g)
+	* Feature: netlink handler for RSS get (-x)
+	* Fix: fix boolean value output in JSON output
+	* Fix: fix build errors and warnings
+
 Version 6.1 - December 19, 2022
 	* Feature: update link mode tables
 	* Feature: register dump for NXP ENETC driver (-d)
diff --git a/cmis.c b/cmis.c
index d0b6272..531932e 100644
--- a/cmis.c
+++ b/cmis.c
@@ -139,6 +139,44 @@
 	printf("\t%-41s : Rev. %d.%d\n", "Revision compliance", major, minor);
 }
 
+static void
+cmis_show_signals_one(const struct cmis_memory_map *map, const char *name,
+		      int off, int ioff, unsigned int imask)
+{
+	unsigned int v;
+	int i;
+
+	if (!map->page_01h)
+		return;
+
+	v = 0;
+	for (i = 0; i < CMIS_MAX_BANKS && map->upper_memory[i][0x11]; i++)
+		v |= map->upper_memory[i][0x11][off] << (i * 8);
+
+	if (map->page_01h[ioff] & imask)
+		sff_show_lane_status(name, i * 8, "Yes", "No", v);
+}
+
+static void cmis_show_signals(const struct cmis_memory_map *map)
+{
+	cmis_show_signals_one(map, "Rx loss of signal", CMIS_RX_LOS_OFFSET,
+			      CMIS_DIAG_FLAGS_RX_OFFSET, CMIS_DIAG_FL_RX_LOS);
+	cmis_show_signals_one(map, "Tx loss of signal", CMIS_TX_LOS_OFFSET,
+			      CMIS_DIAG_FLAGS_TX_OFFSET, CMIS_DIAG_FL_TX_LOS);
+
+	cmis_show_signals_one(map, "Rx loss of lock", CMIS_RX_LOL_OFFSET,
+			      CMIS_DIAG_FLAGS_RX_OFFSET, CMIS_DIAG_FL_RX_LOL);
+	cmis_show_signals_one(map, "Tx loss of lock", CMIS_TX_LOL_OFFSET,
+			      CMIS_DIAG_FLAGS_TX_OFFSET, CMIS_DIAG_FL_TX_LOL);
+
+	cmis_show_signals_one(map, "Tx fault", CMIS_TX_FAIL_OFFSET,
+			      CMIS_DIAG_FLAGS_TX_OFFSET, CMIS_DIAG_FL_TX_FAIL);
+
+	cmis_show_signals_one(map, "Tx adaptive eq fault",
+			      CMIS_TX_EQ_FAIL_OFFSET, CMIS_DIAG_FLAGS_TX_OFFSET,
+			      CMIS_DIAG_FL_TX_ADAPTIVE_EQ_FAIL);
+}
+
 /**
  * Print information about the device's power consumption.
  * Relevant documents:
@@ -857,6 +895,7 @@
 	cmis_show_link_len(map);
 	cmis_show_vendor_info(map);
 	cmis_show_rev_compliance(map);
+	cmis_show_signals(map);
 	cmis_show_mod_state(map);
 	cmis_show_mod_fault_cause(map);
 	cmis_show_mod_lvl_controls(map);
diff --git a/cmis.h b/cmis.h
index 4679708..8d66f92 100644
--- a/cmis.h
+++ b/cmis.h
@@ -158,6 +158,17 @@
 #define CMIS_DIAG_TYPE_OFFSET			0x97
 #define CMIS_RX_PWR_TYPE_MASK			0x10
 
+/* Supported Flags Advertisement (Page 1) */
+#define CMIS_DIAG_FLAGS_TX_OFFSET		0x9d
+#define CMIS_DIAG_FL_TX_ADAPTIVE_EQ_FAIL	(1 << 3)
+#define CMIS_DIAG_FL_TX_LOL			(1 << 2)
+#define CMIS_DIAG_FL_TX_LOS			(1 << 1)
+#define CMIS_DIAG_FL_TX_FAIL			(1 << 0)
+
+#define CMIS_DIAG_FLAGS_RX_OFFSET		0x9e
+#define CMIS_DIAG_FL_RX_LOL			(1 << 2)
+#define CMIS_DIAG_FL_RX_LOS			(1 << 1)
+
 /* Supported Monitors Advertisement (Page 1) */
 #define CMIS_DIAG_CHAN_ADVER_OFFSET		0xA0
 #define CMIS_TX_BIAS_MON_MASK			0x01
@@ -207,6 +218,10 @@
  */
 
 /* Media Lane-Specific Flags (Page 0x11) */
+#define CMIS_TX_FAIL_OFFSET			0x87
+#define CMIS_TX_LOS_OFFSET			0x88
+#define CMIS_TX_LOL_OFFSET			0x89
+#define CMIS_TX_EQ_FAIL_OFFSET			0x8a
 #define CMIS_TX_PWR_AW_HALARM_OFFSET		0x8B
 #define CMIS_TX_PWR_AW_LALARM_OFFSET		0x8C
 #define CMIS_TX_PWR_AW_HWARN_OFFSET		0x8D
@@ -215,6 +230,8 @@
 #define CMIS_TX_BIAS_AW_LALARM_OFFSET		0x90
 #define CMIS_TX_BIAS_AW_HWARN_OFFSET		0x91
 #define CMIS_TX_BIAS_AW_LWARN_OFFSET		0x92
+#define CMIS_RX_LOS_OFFSET			0x93
+#define CMIS_RX_LOL_OFFSET			0x94
 #define CMIS_RX_PWR_AW_HALARM_OFFSET		0x95
 #define CMIS_RX_PWR_AW_LALARM_OFFSET		0x96
 #define CMIS_RX_PWR_AW_HWARN_OFFSET		0x97
diff --git a/common.c b/common.c
index 2630e73..b8fd4d5 100644
--- a/common.c
+++ b/common.c
@@ -173,3 +173,39 @@
 		fprintf(stdout, "\n");
 	}
 }
+
+void print_indir_table(struct cmd_context *ctx, u64 ring_count,
+		       u32 indir_size, u32 *indir)
+{
+	u32 i;
+
+	printf("RX flow hash indirection table for %s with %llu RX ring(s):\n",
+	       ctx->devname, ring_count);
+
+	if (!indir_size)
+		printf("Operation not supported\n");
+
+	for (i = 0; i < indir_size; i++) {
+		if (i % 8 == 0)
+			printf("%5u: ", i);
+		printf(" %5u", indir[i]);
+		if (i % 8 == 7 || i == indir_size - 1)
+			fputc('\n', stdout);
+	}
+}
+
+void print_rss_hkey(u8 *hkey, u32 hkey_size)
+{
+	u32 i;
+
+	printf("RSS hash key:\n");
+	if (!hkey_size || !hkey)
+		printf("Operation not supported\n");
+
+	for (i = 0; i < hkey_size; i++) {
+		if (i == (hkey_size - 1))
+			printf("%02x\n", hkey[i]);
+		else
+			printf("%02x:", hkey[i]);
+	}
+}
diff --git a/common.h b/common.h
index b74fdfa..f975407 100644
--- a/common.h
+++ b/common.h
@@ -8,6 +8,8 @@
 #define ETHTOOL_COMMON_H__
 
 #include "internal.h"
+#include <stddef.h>
+#include <errno.h>
 
 #define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
 
@@ -41,5 +43,7 @@
 void print_flags(const struct flag_info *info, unsigned int n_info, u32 value);
 int dump_wol(struct ethtool_wolinfo *wol);
 void dump_mdix(u8 mdix, u8 mdix_ctrl);
-
+void print_indir_table(struct cmd_context *ctx, u64 ring_count,
+		       u32 indir_size, u32 *indir);
+void print_rss_hkey(u8 *hkey, u32 hkey_size);
 #endif /* ETHTOOL_COMMON_H__ */
diff --git a/configure.ac b/configure.ac
index 3eb4e7b..11efb99 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,7 @@
 dnl Process this file with autoconf to produce a configure script.
-AC_INIT(ethtool, 6.1, netdev@vger.kernel.org)
+AC_INIT(ethtool, 6.5, netdev@vger.kernel.org)
 AC_PREREQ(2.52)
+AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_SRCDIR([ethtool.c])
 AM_INIT_AUTOMAKE([gnu subdir-objects])
 AC_CONFIG_HEADERS([ethtool-config.h])
@@ -13,22 +14,25 @@
 AM_PROG_CC_C_O
 PKG_PROG_PKG_CONFIG
 
+AC_DEFUN([AX_CHECK_STDC],
+	 [AX_CHECK_COMPILE_FLAG([-std=gnu11],
+		[AX_APPEND_FLAG([-std=gnu11])],
+		[AX_CHECK_COMPILE_FLAG([-std=c11],
+			[AX_APPEND_FLAG([-std=c11])],
+			[AC_MSG_ERROR([$PACKAGE requires a C11 compiler])])
+		])
+	])
+AX_CHECK_STDC
+
 dnl Checks for libraries.
 
 dnl Checks for header files.
 
 dnl Checks for typedefs, structures, and compiler characteristics.
-AC_MSG_CHECKING([whether <linux/types.h> defines big-endian types])
-AC_TRY_COMPILE([#include <linux/types.h>],
-	       [__be16 foo;__be32 bar;],
-	       [AC_MSG_RESULT(yes)
-		AC_DEFINE([HAVE_BE_TYPES], [1],
-			  [Define to 1 if <linux/types.h> defines big-endian types])],
-	       [AC_MSG_RESULT(no)])
 
 dnl Checks for library functions.
 AC_HEADER_STDC
-AC_CHECK_FUNCS(socket strtol)
+AC_CHECK_FUNCS(socket)
 
 dnl Check for options
 AC_ARG_ENABLE(pretty-dump,
diff --git a/ethtool.8.in b/ethtool.8.in
index bee47f2..c0c37a4 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -117,7 +117,7 @@
 .  hy \\n(HY
 ..
 .
-.TH ETHTOOL 8 "December 2022" "Ethtool version @VERSION@"
+.TH ETHTOOL 8 "September 2023" "Ethtool version @VERSION@"
 .SH NAME
 ethtool \- query or control network driver and hardware settings
 .
@@ -188,6 +188,9 @@
 .BN sample\-interval
 .B2 cqe\-mode\-rx on off
 .B2 cqe\-mode\-tx on off
+.BN tx\-aggr\-max\-bytes
+.BN tx\-aggr\-max\-frames
+.BN tx\-aggr\-time\-usecs
 .HP
 .B ethtool \-g|\-\-show\-ring
 .I devname
@@ -201,6 +204,8 @@
 .BN rx\-buf\-len
 .BN cqe\-size
 .BN tx\-push
+.BN rx\-push
+.BN tx\-push\-buf\-len
 .HP
 .B ethtool \-i|\-\-driver
 .I devname
@@ -468,7 +473,6 @@
 .IR %x ]
 .I sub_command
 .RB ...
- .
 .HP
 .B ethtool \-\-cable\-test
 .I devname
@@ -490,6 +494,46 @@
 .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 ]
+.HP
+.B ethtool \-\-show\-pse
+.I devname
+.HP
+.B ethtool \-\-set\-pse
+.I devname
+.RB [ podl\-pse\-admin\-control
+.BR enable | disable ]
 .
 .\" Adjust lines (i.e. full justification) and hyphenate.
 .ad
@@ -533,6 +577,15 @@
 .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 +634,13 @@
 .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.
+.TP
+.BI tx\-push\-buf\-len \ N
+Specifies the maximum number of bytes of a transmitted packet a driver can push
+directly to the underlying device
 .RE
 .TP
 .B \-i \-\-driver
@@ -698,6 +758,10 @@
 .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 +840,9 @@
 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
@@ -853,6 +920,12 @@
 0x8000000000000000000000	400000baseLR4_ER4_FR4 Full
 0x10000000000000000000000	400000baseDR4 Full
 0x20000000000000000000000	400000baseCR4 Full
+0x200000000000000000000000	800000baseCR8 Full
+0x400000000000000000000000	800000baseKR8 Full
+0x800000000000000000000000	800000baseDR8 Full
+0x1000000000000000000000000	800000baseDR8_2 Full
+0x2000000000000000000000000	800000baseSR8 Full
+0x4000000000000000000000000	800000baseVR8 Full
 .TE
 .TP
 .BI phyad \ N
@@ -1505,6 +1578,178 @@
 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
+.TP
+.B \-\-show\-pse
+Show the current Power Sourcing Equipment (PSE) status for the given interface.
+.RS 4
+.TP
+.B podl-pse-admin-state
+This attribute indicates the operational status of PoDL PSE functions, which
+can be modified using the
+.B podl-pse-admin-control
+parameter. It corresponds to IEEE 802.3-2018 30.15.1.1.2 (aPoDLPSEAdminState),
+with potential values being
+.B enabled, disabled
+.TP
+.B podl-pse-power-detection-status
+This attribute indicates the power detection status of the PoDL PSE. The
+status depend on internal PSE state machine and automatic PD classification
+support. It corresponds to IEEE 802.3-2018 30.15.1.1.3
+(aPoDLPSEPowerDetectionStatus) with potential values being
+.B disabled, searching, delivering power, sleep, idle, error
+.RE
+
+.RE
+.TP
+.B \-\-set\-pse
+Set Power Sourcing Equipment (PSE) parameters.
+.RS 4
+.TP
+.A2 podl-pse-admin-control \ enable disable
+This parameter manages PoDL PSE Admin operations in accordance with the IEEE
+802.3-2018 30.15.1.2.1 (acPoDLPSEAdminControl) specification.
+
 .SH BUGS
 Not supported (in part or whole) on all network drivers.
 .SH AUTHOR
diff --git a/ethtool.c b/ethtool.c
index 526be4c..af51220 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -58,10 +58,6 @@
 #define MAX_ADDR_LEN	32
 #endif
 
-#ifndef NETLINK_GENERIC
-#define NETLINK_GENERIC	16
-#endif
-
 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
 
 static void exit_bad_args(void) __attribute__((noreturn));
@@ -478,6 +474,15 @@
 		ETHTOOL_LINK_MODE_100baseFX_Half_BIT,
 		ETHTOOL_LINK_MODE_100baseFX_Full_BIT,
 		ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
+		ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT,
+		ETHTOOL_LINK_MODE_800000baseKR8_Full_BIT,
+		ETHTOOL_LINK_MODE_800000baseDR8_Full_BIT,
+		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[] = {
@@ -720,6 +725,24 @@
 		  "100baseFX/Full" },
 		{ 0, ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
 		  "10baseT1L/Full" },
+		{ 0, ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT,
+		  "800000baseCR8/Full" },
+		{ 0, ETHTOOL_LINK_MODE_800000baseKR8_Full_BIT,
+		  "800000baseKR8/Full" },
+		{ 0, ETHTOOL_LINK_MODE_800000baseDR8_Full_BIT,
+		  "800000baseDR8/Full" },
+		{ 0, ETHTOOL_LINK_MODE_800000baseDR8_2_Full_BIT,
+		  "800000baseDR8_2/Full" },
+		{ 0, ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT,
+		  "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;
@@ -1138,6 +1161,7 @@
 	{ "lan743x", lan743x_dump_regs },
 	{ "fsl_enetc", fsl_enetc_dump_regs },
 	{ "fsl_enetc_vf", fsl_enetc_dump_regs },
+	{ "hns3", hns3_dump_regs },
 };
 #endif
 
@@ -3882,27 +3906,6 @@
 	return err ? 1 : 0;
 }
 
-static void print_indir_table(struct cmd_context *ctx,
-			      struct ethtool_rxnfc *ring_count,
-			      u32 indir_size, u32 *indir)
-{
-	u32 i;
-
-	printf("RX flow hash indirection table for %s with %llu RX ring(s):\n",
-	       ctx->devname, ring_count->data);
-
-	if (!indir_size)
-		printf("Operation not supported\n");
-
-	for (i = 0; i < indir_size; i++) {
-		if (i % 8 == 0)
-			printf("%5u: ", i);
-		printf(" %5u", indir[i]);
-		if (i % 8 == 7 || i == indir_size - 1)
-			fputc('\n', stdout);
-	}
-}
-
 static int do_grxfhindir(struct cmd_context *ctx,
 			 struct ethtool_rxnfc *ring_count)
 {
@@ -3934,7 +3937,8 @@
 		return 1;
 	}
 
-	print_indir_table(ctx, ring_count, indir->size, indir->ring_index);
+	print_indir_table(ctx, ring_count->data, indir->size,
+			  indir->ring_index);
 
 	free(indir);
 	return 0;
@@ -3949,7 +3953,7 @@
 	u32 rss_context = 0;
 	u32 i, indir_bytes;
 	unsigned int arg_num = 0;
-	char *hkey;
+	u8 *hkey;
 	int err;
 
 	while (arg_num < ctx->argc) {
@@ -3999,21 +4003,13 @@
 		return 1;
 	}
 
-	print_indir_table(ctx, &ring_count, rss->indir_size, rss->rss_config);
+	print_indir_table(ctx, ring_count.data, rss->indir_size,
+			  rss->rss_config);
 
 	indir_bytes = rss->indir_size * sizeof(rss->rss_config[0]);
-	hkey = ((char *)rss->rss_config + indir_bytes);
+	hkey = ((u8 *)rss->rss_config + indir_bytes);
 
-	printf("RSS hash key:\n");
-	if (!rss->key_size)
-		printf("Operation not supported\n");
-
-	for (i = 0; i < rss->key_size; i++) {
-		if (i == (rss->key_size - 1))
-			printf("%02x\n", (u8) hkey[i]);
-		else
-			printf("%02x:", (u8) hkey[i]);
-	}
+	print_rss_hkey(hkey, rss->key_size);
 
 	printf("RSS hash function:\n");
 	if (!rss->hfunc) {
@@ -5683,7 +5679,8 @@
 		.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",
@@ -5696,6 +5693,7 @@
 	},
 	{
 		.opts	= "-c|--show-coalesce",
+		.json	= true,
 		.func	= do_gcoalesce,
 		.nlfunc	= nl_gcoalesce,
 		.help	= "Show coalesce options"
@@ -5729,9 +5727,13 @@
 			  "		[sample-interval N]\n"
 			  "		[cqe-mode-rx on|off]\n"
 			  "		[cqe-mode-tx on|off]\n"
+			  "		[tx-aggr-max-bytes N]\n"
+			  "		[tx-aggr-max-frames N]\n"
+			  "		[tx-aggr-time-usecs N]\n"
 	},
 	{
 		.opts	= "-g|--show-ring",
+		.json	= true,
 		.func	= do_gring,
 		.nlfunc	= nl_gring,
 		.help	= "Query RX/TX ring parameters"
@@ -5745,9 +5747,11 @@
 			  "		[ 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"
+			  "		[ tx-push-buf-len N]\n"
 	},
 	{
 		.opts	= "-k|--show-features|--show-offload",
@@ -5801,13 +5805,13 @@
 		.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",
@@ -5816,7 +5820,8 @@
 		.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",
@@ -5856,7 +5861,7 @@
 			  "			[ 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"
 	},
 	{
@@ -5867,7 +5872,9 @@
 	},
 	{
 		.opts	= "-x|--show-rxfh-indir|--show-rxfh",
+		.json	= true,
 		.func	= do_grxfh,
+		.nlfunc	= nl_grss,
 		.help	= "Show Rx flow hash indirection table and/or RSS hash key",
 		.xhelp	= "		[ context %d ]\n"
 	},
@@ -5885,7 +5892,7 @@
 		.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",
@@ -5916,10 +5923,10 @@
 		.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",
@@ -5986,16 +5993,16 @@
 		.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",
@@ -6035,14 +6042,14 @@
 		.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",
@@ -6078,6 +6085,55 @@
 		.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	= "--show-pse",
+		.json	= true,
+		.nlfunc	= nl_gpse,
+		.help	= "Show settings for Power Sourcing Equipment",
+	},
+	{
+		.opts	= "--set-pse",
+		.nlfunc	= nl_spse,
+		.help	= "Set Power Sourcing Equipment settings",
+		.xhelp	= "		[ podl-pse-admin-control enable|disable ]\n"
+	},
+	{
 		.opts	= "-h|--help",
 		.no_dev	= true,
 		.func	= show_usage,
@@ -6347,6 +6403,9 @@
 
 	init_global_link_mode_masks();
 
+	if (argc < 2)
+		exit_bad_args();
+
 	/* Skip command name */
 	argp++;
 	argc--;
@@ -6391,7 +6450,7 @@
 	 * name to get settings for (which we don't expect to begin
 	 * with '-').
 	 */
-	if (argc == 0)
+	if (!*argp)
 		exit_bad_args();
 
 	k = find_option(*argp);
diff --git a/hns3.c b/hns3.c
new file mode 100644
index 0000000..7199426
--- /dev/null
+++ b/hns3.c
@@ -0,0 +1,829 @@
+/* Copyright (c) 2023 Huawei Corporation */
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "internal.h"
+
+/* distinguish drive register data of earlier versions */
+#define HNS3_REG_MAGIC_NUMBER 0x686e733372656773 /* hns3regs */
+#define HNS3_REG_RSV_NAME "reserved"
+#define HNS3_REG_UNKNOW_NAME "unknown"
+#define HNS3_REG_UNKNOW_VALUE_LEN 4
+
+struct hns3_reg_tlv {
+	u16 tag;
+	u16 len;
+};
+
+struct hns3_reg_header {
+	u64 magic_number;
+	u8 is_vf;
+	u8 rsv[7];
+};
+
+struct hns3_reg_info {
+	const char *name;
+	u16 value_len;
+};
+
+struct hns3_regs_group {
+	const char *group_name;
+	const struct hns3_reg_info *regs;
+	u16 regs_count;
+};
+
+enum hns3_reg_tag {
+	HNS3_TAG_CMDQ = 0,
+	HNS3_TAG_COMMON,
+	HNS3_TAG_RING,
+	HNS3_TAG_TQP_INTR,
+	HNS3_TAG_QUERY_32_BIT,
+	HNS3_TAG_QUERY_64_BIT,
+	HNS3_TAG_DFX_BIOS_COMMON,
+	HNS3_TAG_DFX_SSU_0,
+	HNS3_TAG_DFX_SSU_1,
+	HNS3_TAG_DFX_IGU_EGU,
+	HNS3_TAG_DFX_RPU_0,
+	HNS3_TAG_DFX_RPU_1,
+	HNS3_TAG_DFX_NCSI,
+	HNS3_TAG_DFX_RTC,
+	HNS3_TAG_DFX_PPP,
+	HNS3_TAG_DFX_RCB,
+	HNS3_TAG_DFX_TQP,
+	HNS3_TAG_DFX_SSU_2,
+	HNS3_TAG_DFX_RPU_TNL,
+	HNS3_TAG_MAX,
+};
+
+const bool hns3_reg_is_repeat_tag_array[] = {
+	[HNS3_TAG_RING] = true,
+	[HNS3_TAG_TQP_INTR] = true,
+	[HNS3_TAG_DFX_RPU_TNL] = true,
+};
+
+const struct hns3_reg_info pf_cmdq_regs[] = {
+	{"comm_nic_csq_baseaddr_l", 4},
+	{"comm_nic_csq_baseaddr_h", 4},
+	{"comm_nic_csq_depth", 4},
+	{"comm_nic_csq_tail", 4},
+	{"comm_nic_csq_head", 4},
+	{"comm_nic_crq_baseaddr_l", 4},
+	{"comm_nic_crq_baseaddr_h", 4},
+	{"comm_nic_crq_depth", 4},
+	{"comm_nic_crq_tail", 4},
+	{"comm_nic_crq_head", 4},
+	{"comm_vector0_cmdq_src", 4},
+	{"comm_cmdq_intr_sts", 4},
+	{"comm_cmdq_intr_en", 4},
+	{"comm_cmdq_intr_gen", 4},
+};
+
+const struct hns3_reg_info pf_common_regs[] = {
+	{"misc_vector_base", 4},
+	{"pf_other_int", 4},
+	{"misc_reset_sts", 4},
+	{"misc_vector_int_sts", 4},
+	{"global_reset", 4},
+	{"fun_rst_ing", 4},
+	{"gro_en", 4},
+};
+
+const struct hns3_reg_info pf_ring_regs[] = {
+	{"ring_rx_addr_l", 4},
+	{"ring_rx_addr_h", 4},
+	{"ring_rx_bd_num", 4},
+	{"ring_rx_bd_length", 4},
+	{"ring_rx_merge_en", 4},
+	{"ring_rx_tail", 4},
+	{"ring_rx_head", 4},
+	{"ring_rx_fbd_num", 4},
+	{"ring_rx_offset", 4},
+	{"ring_rx_fbd_offset", 4},
+	{"ring_rx_stash", 4},
+	{"ring_rx_bd_err", 4},
+	{"ring_tx_addr_l", 4},
+	{"ring_tx_addr_h", 4},
+	{"ring_tx_bd_num", 4},
+	{"ring_tx_priority", 4},
+	{"ring_tx_tc", 4},
+	{"ring_tx_merge_en", 4},
+	{"ring_tx_tail", 4},
+	{"ring_tx_head", 4},
+	{"ring_tx_fbd_num", 4},
+	{"ring_tx_offset", 4},
+	{"ring_tx_ebd_num", 4},
+	{"ring_tx_ebd_offset", 4},
+	{"ring_tx_bd_err", 4},
+	{"ring_en", 4},
+};
+
+const struct hns3_reg_info pf_tqp_intr_regs[] = {
+	{"tqp_intr_ctrl", 4},
+	{"tqp_intr_gl0", 4},
+	{"tqp_intr_gl1", 4},
+	{"tqp_intr_gl2", 4},
+	{"tqp_intr_rl", 4},
+};
+
+const struct hns3_reg_info query_32_bit_regs[] = {
+	{"ssu_common_err_int", 4},
+	{"ssu_port_based_err_int", 4},
+	{"ssu_fifo_overflow_int", 4},
+	{"ssu_ets_tcg_int", 4},
+	{"ssu_bp_status_0", 4},
+	{"ssu_bp_status_1", 4},
+	{"ssu_bp_status_2", 4},
+	{"ssu_bp_status_3", 4},
+	{"ssu_bp_status_4", 4},
+	{"ssu_bp_status_5", 4},
+	{"ssu_mac_tx_pfc_ind", 4},
+	{"ssu_mac_rx_pfc_ind", 4},
+	{"ssu_rx_oq_drop_pkt_cnt", 4},
+	{"ssu_tx_oq_drop_pkt_cnt", 4},
+};
+
+const struct hns3_reg_info query_64_bit_regs[] = {
+	{"ppp_get_rx_pkt_cnt", 8},
+	{"ppp_get_tx_pkt_cnt", 8},
+	{"ppp_send_uc_prt2host_pkt_cnt", 8},
+	{"ppp_send_uc_prt2prt_pkt_cnt", 8},
+	{"ppp_send_uc_host2host_pkt_cnt", 8},
+	{"ppp_send_uc_host2prt_pkt_cnt", 8},
+	{"ppp_send_mc_from_prt_cnt", 8},
+};
+
+const struct hns3_reg_info dfx_bios_common_regs[] = {
+	{HNS3_REG_RSV_NAME, 4},
+	{"bp_cpu_state", 4},
+	{"dfx_msix_info_nic_0", 4},
+	{"dfx_msix_info_nic_1", 4},
+	{"dfx_msix_info_nic_2", 4},
+	{"dfx_msix_info_nic_3", 4},
+	{"dfx_msix_info_roc_0", 4},
+	{"dfx_msix_info_roc_1", 4},
+	{"dfx_msix_info_roc_2", 4},
+	{"dfx_msix_info_roc_3", 4},
+	{HNS3_REG_RSV_NAME, 8},
+};
+
+const struct hns3_reg_info dfx_ssu_0_regs[] = {
+	{HNS3_REG_RSV_NAME, 4},
+	{"ssu_ets_port_status", 4},
+	{"ssu_ets_tcg_status", 4},
+	{HNS3_REG_RSV_NAME, 4},
+	{HNS3_REG_RSV_NAME, 4},
+	{"ssu_bp_status_0", 4},
+	{"ssu_bp_status_1", 4},
+	{"ssu_bp_status_2", 4},
+	{"ssu_bp_status_3", 4},
+	{"ssu_bp_status_4", 4},
+	{"ssu_bp_status_5", 4},
+	{"ssu_mac_tx_pfc_ind", 4},
+	{"mac_ssu_rx_pfc_ind", 4},
+	{"btmp_ageing_st_b0", 4},
+	{"btmp_ageing_st_b1", 4},
+	{"btmp_ageing_st_b2", 4},
+	{HNS3_REG_RSV_NAME, 8},
+	{"full_drop_num", 4},
+	{"part_drop_num", 4},
+	{"ppp_key_drop_num", 4},
+	{"ppp_rlt_drop_num", 4},
+	{"lo_pri_unicast_rlt_drop_num", 4},
+	{"hi_pri_multicast_rlt_drop_num", 4},
+	{"lo_pri_multicast_rlt_drop_num", 4},
+	{"ncsi_packet_curr_buffer_cnt", 4},
+	{HNS3_REG_RSV_NAME, 12},
+	{"ssu_mb_rd_rlt_drop_cnt", 4},
+	{"ssu_ppp_mac_key_num", 8},
+	{"ssu_ppp_host_key_num", 8},
+	{"ppp_ssu_mac_rlt_num", 8},
+	{"ppp_ssu_host_rlt_num", 8},
+	{"ncsi_rx_packet_in_cnt", 8},
+	{"ncsi_tx_packet_out_cnt", 8},
+	{"ssu_key_drop_num", 4},
+	{"mb_uncopy_num", 4},
+	{"rx_oq_drop_pkt_cnt", 4},
+	{"tx_oq_drop_pkt_cnt", 4},
+	{"bank_unbalance_drop_cnt", 4},
+	{"bank_unbalance_rx_drop_cnt", 4},
+	{"nic_l2_err_drop_pkt_cnt", 4},
+	{"roc_l2_err_drop_pkt_cnt", 4},
+	{"nic_l2_err_drop_pkt_cnt_rx", 4},
+	{"roc_l2_err_drop_pkt_cnt_rx", 4},
+	{"rx_oq_glb_drop_pkt_cnt", 4},
+	{HNS3_REG_RSV_NAME, 4},
+	{"lo_pri_unicast_cur_cnt", 4},
+	{"hi_pri_multicast_cur_cnt", 4},
+	{"lo_pri_multicast_cur_cnt", 4},
+	{HNS3_REG_RSV_NAME, 12},
+};
+
+const struct hns3_reg_info dfx_ssu_1_regs[] = {
+	{"prt_id", 4},
+	{"packet_tc_curr_buffer_cnt_0", 4},
+	{"packet_tc_curr_buffer_cnt_1", 4},
+	{"packet_tc_curr_buffer_cnt_2", 4},
+	{"packet_tc_curr_buffer_cnt_3", 4},
+	{"packet_tc_curr_buffer_cnt_4", 4},
+	{"packet_tc_curr_buffer_cnt_5", 4},
+	{"packet_tc_curr_buffer_cnt_6", 4},
+	{"packet_tc_curr_buffer_cnt_7", 4},
+	{"packet_curr_buffer_cnt", 4},
+	{HNS3_REG_RSV_NAME, 8},
+	{"rx_packet_in_cnt", 8},
+	{"rx_packet_out_cnt", 8},
+	{"tx_packet_in_cnt", 8},
+	{"tx_packet_out_cnt", 8},
+	{"roc_rx_packet_in_cnt", 8},
+	{"roc_tx_packet_out_cnt", 8},
+	{"rx_packet_tc_in_cnt_0", 8},
+	{"rx_packet_tc_in_cnt_1", 8},
+	{"rx_packet_tc_in_cnt_2", 8},
+	{"rx_packet_tc_in_cnt_3", 8},
+	{"rx_packet_tc_in_cnt_4", 8},
+	{"rx_packet_tc_in_cnt_5", 8},
+	{"rx_packet_tc_in_cnt_6", 8},
+	{"rx_packet_tc_in_cnt_7", 8},
+	{"rx_packet_tc_out_cnt_0", 8},
+	{"rx_packet_tc_out_cnt_1", 8},
+	{"rx_packet_tc_out_cnt_2", 8},
+	{"rx_packet_tc_out_cnt_3", 8},
+	{"rx_packet_tc_out_cnt_4", 8},
+	{"rx_packet_tc_out_cnt_5", 8},
+	{"rx_packet_tc_out_cnt_6", 8},
+	{"rx_packet_tc_out_cnt_7", 8},
+	{"tx_packet_tc_in_cnt_0", 8},
+	{"tx_packet_tc_in_cnt_1", 8},
+	{"tx_packet_tc_in_cnt_2", 8},
+	{"tx_packet_tc_in_cnt_3", 8},
+	{"tx_packet_tc_in_cnt_4", 8},
+	{"tx_packet_tc_in_cnt_5", 8},
+	{"tx_packet_tc_in_cnt_6", 8},
+	{"tx_packet_tc_in_cnt_7", 8},
+	{"tx_packet_tc_out_cnt_0", 8},
+	{"tx_packet_tc_out_cnt_1", 8},
+	{"tx_packet_tc_out_cnt_2", 8},
+	{"tx_packet_tc_out_cnt_3", 8},
+	{"tx_packet_tc_out_cnt_4", 8},
+	{"tx_packet_tc_out_cnt_5", 8},
+	{"tx_packet_tc_out_cnt_6", 8},
+	{"tx_packet_tc_out_cnt_7", 8},
+	{HNS3_REG_RSV_NAME, 8},
+};
+
+const struct hns3_reg_info dfx_igu_egu_regs[] = {
+	{"prt_id", 4},
+	{"igu_rx_err_pkt", 4},
+	{"igu_rx_no_sof_pkt", 4},
+	{"egu_tx_1588_short_pkt", 4},
+	{"egu_tx_1588_pkt", 4},
+	{"egu_tx_err_pkt", 4},
+	{"igu_rx_out_l2_pkt", 4},
+	{"igu_rx_out_l3_pkt", 4},
+	{"igu_rx_out_l4_pkt", 4},
+	{"igu_rx_in_l2_pkt", 4},
+	{"igu_rx_in_l3_pkt", 4},
+	{"igu_rx_in_l4_pkt", 4},
+	{"igu_rx_el3e_pkt", 4},
+	{"igu_rx_el4e_pkt", 4},
+	{"igu_rx_l3e_pkt", 4},
+	{"igu_rx_l4e_pkt", 4},
+	{"igu_rx_rocee_pkt", 4},
+	{"igu_rx_out_udp0_pkt", 4},
+	{"igu_rx_in_udp0_pkt", 4},
+	{"mul_car_drop_pkt_cnt", 8},
+	{"bro_car_drop_pkt_cnt", 8},
+	{HNS3_REG_RSV_NAME, 4},
+	{"igu_rx_oversize_pkt", 8},
+	{"igu_rx_undersize_pkt", 8},
+	{"igu_rx_out_all_pkt", 8},
+	{"igu_tx_out_all_pkt", 8},
+	{"igu_rx_uni_pkt", 8},
+	{"igu_rx_multi_pkt", 8},
+	{"igu_rx_broad_pkt", 8},
+	{"egu_tx_out_all_pkt", 8},
+	{"egu_tx_uni_pkt", 8},
+	{"egu_tx_multi_pkt", 8},
+	{"egu_tx_broad_pkt", 8},
+	{"igu_tx_key_num", 8},
+	{"igu_rx_non_tun_pkt", 8},
+	{"igu_rx_tun_pkt", 8},
+	{HNS3_REG_RSV_NAME, 8},
+};
+
+const struct hns3_reg_info dfx_rpu_0_regs[] = {
+	{HNS3_REG_RSV_NAME, 4},
+	{"fsm_dfx_st0", 4},
+	{"fsm_dfx_st1", 4},
+	{"rpu_rx_pkt_drop_cnt", 4},
+	{"buf_wait_timeout", 4},
+	{"buf_wait_timeout_qid", 4},
+};
+
+const struct hns3_reg_info dfx_rpu_1_regs[] = {
+	{HNS3_REG_RSV_NAME, 4},
+	{"fifo_dfx_st0", 4},
+	{"fifo_dfx_st1", 4},
+	{"fifo_dfx_st2", 4},
+	{"fifo_dfx_st3", 4},
+	{"fifo_dfx_st4", 4},
+	{"fifo_dfx_st5", 4},
+	{HNS3_REG_RSV_NAME, 20},
+};
+
+const struct hns3_reg_info dfx_ncsi_regs[] = {
+	{HNS3_REG_RSV_NAME, 4},
+	{"ncsi_egu_tx_fifo_sts", 4},
+	{"ncsi_pause_status", 4},
+	{"ncsi_rx_ctrl_dmac_err_cnt", 4},
+	{"ncsi_rx_ctrl_smac_err_cnt", 4},
+	{"ncsi_rx_ctrl_cks_err_cnt", 4},
+	{"ncsi_rx_ctrl_pkt_cnt", 4},
+	{"ncsi_rx_pt_dmac_err_cnt", 4},
+	{"ncsi_rx_pt_smac_err_cnt", 4},
+	{"ncsi_rx_pt_pkt_cnt", 4},
+	{"ncsi_rx_fcs_err_cnt", 4},
+	{"ncsi_tx_ctrl_dmac_err_cnt", 4},
+	{"ncsi_tx_ctrl_smac_err_cnt", 4},
+	{"ncsi_tx_ctrl_pkt_cnt", 4},
+	{"ncsi_tx_pt_dmac_err_cnt", 4},
+	{"ncsi_tx_pt_smac_err_cnt", 4},
+	{"ncsi_tx_pt_pkt_cnt", 4},
+	{"ncsi_tx_pt_pkt_trun_cnt", 4},
+	{"ncsi_tx_pt_pkt_err_cnt", 4},
+	{"ncsi_tx_ctrl_pkt_err_cnt", 4},
+	{"ncsi_rx_ctrl_pkt_trun_cnt", 4},
+	{"ncsi_rx_ctrl_pkt_cflit_cnt", 4},
+	{HNS3_REG_RSV_NAME, 8},
+	{"ncsi_mac_rx_octets_ok", 4},
+	{"ncsi_mac_rx_octets_bad", 4},
+	{"ncsi_mac_rx_uc_pkts", 4},
+	{"ncsi_mac_rx_mc_pkts", 4},
+	{"ncsi_mac_rx_bc_pkts", 4},
+	{"ncsi_mac_rx_pkts_64octets", 4},
+	{"ncsi_mac_rx_pkts_65to127octets", 4},
+	{"ncsi_mac_rx_pkts_128to255octets", 4},
+	{"ncsi_mac_rx_pkts_256to511octets", 4},
+	{"ncsi_mac_rx_pkts_512to1023octets", 4},
+	{"ncsi_mac_rx_pkts_1024to1518octets", 4},
+	{"ncsi_mac_rx_pkts_1519tomaxoctets", 4},
+	{"ncsi_mac_rx_fcs_errors", 4},
+	{"ncsi_mac_rx_long_errors", 4},
+	{"ncsi_mac_rx_jabber_errors", 4},
+	{"ncsi_mac_rx_runt_err_cnt", 4},
+	{"ncsi_mac_rx_short_err_cnt", 4},
+	{"ncsi_mac_rx_filt_pkt_cnt", 4},
+	{"ncsi_mac_rx_octets_total_filt", 4},
+	{"ncsi_mac_tx_octets_ok", 4},
+	{"ncsi_mac_tx_octets_bad", 4},
+	{"ncsi_mac_tx_uc_pkts", 4},
+	{"ncsi_mac_tx_mc_pkts", 4},
+	{"ncsi_mac_tx_bc_pkts", 4},
+	{"ncsi_mac_tx_pkts_64octets", 4},
+	{"ncsi_mac_tx_pkts_65to127octets", 4},
+	{"ncsi_mac_tx_pkts_128to255octets", 4},
+	{"ncsi_mac_tx_pkts_256to511octets", 4},
+	{"ncsi_mac_tx_pkts_512to1023octets", 4},
+	{"ncsi_mac_tx_pkts_1024to1518octets", 4},
+	{"ncsi_mac_tx_pkts_1519tomaxoctets", 4},
+	{"ncsi_mac_tx_underrun", 4},
+	{"ncsi_mac_tx_crc_error", 4},
+	{"ncsi_mac_tx_pause_frames", 4},
+	{"ncsi_mac_rx_pad_pkts", 4},
+	{"ncsi_mac_rx_pause_frames", 4},
+};
+
+const struct hns3_reg_info dfx_rtc_regs[] = {
+	{HNS3_REG_RSV_NAME, 4},
+	{"lge_igu_afifo_dfx_0", 4},
+	{"lge_igu_afifo_dfx_1", 4},
+	{"lge_igu_afifo_dfx_2", 4},
+	{"lge_igu_afifo_dfx_3", 4},
+	{"lge_igu_afifo_dfx_4", 4},
+	{"lge_igu_afifo_dfx_5", 4},
+	{"lge_igu_afifo_dfx_6", 4},
+	{"lge_igu_afifo_dfx_7", 4},
+	{"lge_egu_afifo_dfx_0", 4},
+	{"lge_egu_afifo_dfx_1", 4},
+	{"lge_egu_afifo_dfx_2", 4},
+	{"lge_egu_afifo_dfx_3", 4},
+	{"lge_egu_afifo_dfx_4", 4},
+	{"lge_egu_afifo_dfx_5", 4},
+	{"lge_egu_afifo_dfx_6", 4},
+	{"lge_egu_afifo_dfx_7", 4},
+	{"cge_igu_afifo_dfx_0", 4},
+	{"cge_igu_afifo_dfx_1", 4},
+	{"cge_egu_afifo_dfx_0", 4},
+	{"cge_egu_afifo_dfx_1", 4},
+	{HNS3_REG_RSV_NAME, 12},
+};
+
+const struct hns3_reg_info dfx_ppp_regs[] = {
+	{HNS3_REG_RSV_NAME, 4},
+	{"drop_from_prt_pkt_cnt", 4},
+	{"drop_from_host_pkt_cnt", 4},
+	{"drop_tx_vlan_proc_cnt", 4},
+	{"drop_mng_cnt", 4},
+	{"drop_fd_cnt", 4},
+	{"drop_no_dst_cnt", 4},
+	{"drop_mc_mbid_full_cnt", 4},
+	{"drop_sc_filtered", 4},
+	{"ppp_mc_drop_pkt_cnt", 4},
+	{"drop_pt_cnt", 4},
+	{"drop_mac_anti_spoof_cnt", 4},
+	{"drop_ig_vfv_cnt", 4},
+	{"drop_ig_prtv_cnt", 4},
+	{"drop_cnm_pfc_pause_cnt", 4},
+	{"drop_torus_tc_cnt", 4},
+	{"drop_torus_lpbk_cnt", 4},
+	{"ppp_hfs_sts", 4},
+	{"ppp_mc_rslt_sts", 4},
+	{"ppp_p3u_sts", 4},
+	{HNS3_REG_RSV_NAME, 4},
+	{"ppp_umv_sts_0", 4},
+	{"ppp_umv_sts_1", 4},
+	{"ppp_vfv_sts", 4},
+	{"ppp_gro_key_cnt", 4},
+	{"ppp_gro_info_cnt", 4},
+	{"ppp_gro_drop_cnt", 4},
+	{"ppp_gro_out_cnt", 4},
+	{"ppp_gro_key_match_data_cnt", 4},
+	{"ppp_gro_key_match_tcam_cnt", 4},
+	{"ppp_gro_info_match_cnt", 4},
+	{"ppp_gro_free_entry_cnt", 4},
+	{"ppp_gro_inner_dfx_signal", 4},
+	{HNS3_REG_RSV_NAME, 12},
+	{"get_rx_pkt_cnt", 8},
+	{"get_tx_pkt_cnt", 8},
+	{"send_uc_prt2host_pkt_cnt", 8},
+	{"send_uc_prt2prt_pkt_cnt", 8},
+	{"send_uc_host2host_pkt_cnt", 8},
+	{"send_uc_host2prt_pkt_cnt", 8},
+	{"send_mc_from_prt_cnt", 8},
+	{"send_mc_from_host_cnt", 8},
+	{"ssu_mc_rd_cnt", 8},
+	{"ssu_mc_drop_cnt", 8},
+	{"ssu_mc_rd_pkt_cnt", 8},
+	{"ppp_mc_2host_pkt_cnt", 8},
+	{"ppp_mc_2prt_pkt_cnt", 8},
+	{"ntsnos_pkt_cnt", 8},
+	{"ntup_pkt_cnt", 8},
+	{"ntlcl_pkt_cnt", 8},
+	{"nttgt_pkt_cnt", 8},
+	{"rtns_pkt_cnt", 8},
+	{"rtlpbk_pkt_cnt", 8},
+	{"nr_pkt_cnt", 8},
+	{"rr_pkt_cnt", 8},
+	{"mng_tbl_hit_cnt", 8},
+	{"fd_tbl_hit_cnt", 8},
+	{"fd_lkup_cnt", 8},
+	{"bc_hit_cnt", 8},
+	{"um_tbl_uc_hit_cnt", 8},
+	{"um_tbl_mc_hit_cnt", 8},
+	{"um_tbl_snq_hit_cnt", 8},
+	{HNS3_REG_RSV_NAME, 8},
+	{"fwd_bonding_hit_cnt", 8},
+	{"promis_tbl_hit_cnt", 8},
+	{"get_tunl_pkt_cnt", 8},
+	{"get_bmc_pkt_cnt", 8},
+	{"send_uc_prt2bmc_pkt_cnt", 8},
+	{"send_uc_host2bmc_pkt_cnt", 8},
+	{"send_uc_bmc2host_pkt_cnt", 8},
+	{"send_uc_bmc2prt_pkt_cnt", 8},
+	{"ppp_mc_2bmc_pkt_cnt", 8},
+	{HNS3_REG_RSV_NAME, 24},
+	{"rx_default_host_hit_cnt", 8},
+	{"lan_pair_cnt", 8},
+	{"um_tbl_mc_hit_pkt_cnt", 8},
+	{"mta_tbl_hit_pkt_cnt", 8},
+	{"promis_tbl_hit_pkt_cnt", 8},
+	{HNS3_REG_RSV_NAME, 16},
+};
+
+const struct hns3_reg_info dfx_rcb_regs[] = {
+	{HNS3_REG_RSV_NAME, 4},
+	{"fsm_dfx_st0", 4},
+	{"fsm_dfx_st1", 4},
+	{"fsm_dfx_st2", 4},
+	{"fifo_dfx_st0", 4},
+	{"fifo_dfx_st1", 4},
+	{"fifo_dfx_st2", 4},
+	{"fifo_dfx_st3", 4},
+	{"fifo_dfx_st4", 4},
+	{"fifo_dfx_st5", 4},
+	{"fifo_dfx_st6", 4},
+	{"fifo_dfx_st7", 4},
+	{"fifo_dfx_st8", 4},
+	{"fifo_dfx_st9", 4},
+	{"fifo_dfx_st10", 4},
+	{"fifo_dfx_st11", 4},
+	{"q_credit_vld_0", 4},
+	{"q_credit_vld_1", 4},
+	{"q_credit_vld_2", 4},
+	{"q_credit_vld_3", 4},
+	{"q_credit_vld_4", 4},
+	{"q_credit_vld_5", 4},
+	{"q_credit_vld_6", 4},
+	{"q_credit_vld_7", 4},
+	{"q_credit_vld_8", 4},
+	{"q_credit_vld_9", 4},
+	{"q_credit_vld_10", 4},
+	{"q_credit_vld_11", 4},
+	{"q_credit_vld_12", 4},
+	{"q_credit_vld_13", 4},
+	{"q_credit_vld_14", 4},
+	{"q_credit_vld_15", 4},
+	{"q_credit_vld_16", 4},
+	{"q_credit_vld_17", 4},
+	{"q_credit_vld_18", 4},
+	{"q_credit_vld_19", 4},
+	{"q_credit_vld_20", 4},
+	{"q_credit_vld_21", 4},
+	{"q_credit_vld_22", 4},
+	{"q_credit_vld_23", 4},
+	{"q_credit_vld_24", 4},
+	{"q_credit_vld_25", 4},
+	{"q_credit_vld_26", 4},
+	{"q_credit_vld_27", 4},
+	{"q_credit_vld_28", 4},
+	{"q_credit_vld_29", 4},
+	{"q_credit_vld_30", 4},
+	{"q_credit_vld_31", 4},
+	{"gro_bd_serr_cnt", 4},
+	{"gro_context_serr_cnt", 4},
+	{"rx_stash_cfg_serr_cnt", 4},
+	{"rcb_tx_mem_serr_cnt", 4},
+	{"gro_bd_merr_cnt", 4},
+	{"gro_context_merr_cnt", 4},
+	{"rx_stash_cfg_merr_cnt", 4},
+	{"rcb_tx_mem_merr_cnt", 4},
+	{HNS3_REG_RSV_NAME, 16},
+};
+
+const struct hns3_reg_info dfx_tqp_regs[] = {
+	{"q_num", 4},
+	{"rcb_cfg_rx_ring_tail", 4},
+	{"rcb_cfg_rx_ring_head", 4},
+	{"rcb_cfg_rx_ring_fbdnum", 4},
+	{"rcb_cfg_rx_ring_offset", 4},
+	{"rcb_cfg_rx_ring_fbdoffset", 4},
+	{"rcb_cfg_rx_ring_pktnum_record", 4},
+	{"rcb_cfg_tx_ring_tail", 4},
+	{"rcb_cfg_tx_ring_head", 4},
+	{"rcb_cfg_tx_ring_fbdnum", 4},
+	{"rcb_cfg_tx_ring_offset", 4},
+	{"rcb_cfg_tx_ring_ebdnum", 4},
+};
+
+const struct hns3_reg_info dfx_ssu_2_regs[] = {
+	{"oq_index", 4},
+	{"queue_cnt", 4},
+	{HNS3_REG_RSV_NAME, 16},
+};
+
+const struct hns3_reg_info vf_cmdq_regs[] = {
+	{"comm_nic_csq_baseaddr_l", 4},
+	{"comm_nic_csq_baseaddr_h", 4},
+	{"comm_nic_csq_depth", 4},
+	{"comm_nic_csq_tail", 4},
+	{"comm_nic_csq_head", 4},
+	{"comm_nic_crq_baseaddr_l", 4},
+	{"comm_nic_crq_baseaddr_h", 4},
+	{"comm_nic_crq_depth", 4},
+	{"comm_nic_crq_tail", 4},
+	{"comm_nic_crq_head", 4},
+	{"comm_vector0_cmdq_src", 4},
+	{"comm_vector0_cmdq_state", 4},
+	{"comm_cmdq_intr_en", 4},
+	{"comm_cmdq_intr_gen", 4},
+};
+
+const struct hns3_reg_info vf_common_regs[] = {
+	{"misc_vector_base", 4},
+	{"rst_ing", 4},
+	{"gro_en", 4},
+};
+
+const struct hns3_reg_info vf_ring_regs[] = {
+	{"ring_rx_addr_l", 4},
+	{"ring_rx_addr_h", 4},
+	{"ring_rx_bd_num", 4},
+	{"ring_rx_bd_length", 4},
+	{"ring_rx_merge_en", 4},
+	{"ring_rx_tail", 4},
+	{"ring_rx_head", 4},
+	{"ring_rx_fbd_num", 4},
+	{"ring_rx_offset", 4},
+	{"ring_rx_fbd_offset", 4},
+	{"ring_rx_stash", 4},
+	{"ring_rx_bd_err", 4},
+	{"ring_tx_addr_l", 4},
+	{"ring_tx_addr_h", 4},
+	{"ring_tx_bd_num", 4},
+	{"ring_tx_priority", 4},
+	{"ring_tx_tc", 4},
+	{"ring_tx_merge_en", 4},
+	{"ring_tx_tail", 4},
+	{"ring_tx_head", 4},
+	{"ring_tx_fbd_num", 4},
+	{"ring_tx_offset", 4},
+	{"ring_tx_ebd_num", 4},
+	{"ring_tx_ebd_offset", 4},
+	{"ring_tx_bd_err", 4},
+	{"ring_en", 4},
+};
+
+const struct hns3_reg_info vf_tqp_intr_regs[] = {
+	{"tqp_intr_ctrl", 4},
+	{"tqp_intr_gl0", 4},
+	{"tqp_intr_gl1", 4},
+	{"tqp_intr_gl2", 4},
+	{"tqp_intr_rl", 4},
+};
+
+const struct hns3_regs_group pf_regs_groups[] = {
+	[HNS3_TAG_CMDQ] = {"cmdq_regs", pf_cmdq_regs, ARRAY_SIZE(pf_cmdq_regs)},
+	[HNS3_TAG_COMMON] = {"common_regs", pf_common_regs,
+			     ARRAY_SIZE(pf_common_regs)},
+	[HNS3_TAG_RING] = {"ring_regs", pf_ring_regs, ARRAY_SIZE(pf_ring_regs)},
+	[HNS3_TAG_TQP_INTR] = {"tqp_intr_regs", pf_tqp_intr_regs,
+			       ARRAY_SIZE(pf_tqp_intr_regs)},
+	[HNS3_TAG_QUERY_32_BIT] = {"dfx_32_regs", query_32_bit_regs,
+				   ARRAY_SIZE(query_32_bit_regs)},
+	[HNS3_TAG_QUERY_64_BIT] = {"dfx_64_regs", query_64_bit_regs,
+				   ARRAY_SIZE(query_64_bit_regs)},
+	[HNS3_TAG_DFX_BIOS_COMMON] = {"dfx_bios_common_regs",
+				      dfx_bios_common_regs,
+				      ARRAY_SIZE(dfx_bios_common_regs)},
+	[HNS3_TAG_DFX_SSU_0] = {"dfx_ssu_0_regs", dfx_ssu_0_regs,
+				ARRAY_SIZE(dfx_ssu_0_regs)},
+	[HNS3_TAG_DFX_SSU_1] = {"dfx_ssu_1_regs", dfx_ssu_1_regs,
+				ARRAY_SIZE(dfx_ssu_1_regs)},
+	[HNS3_TAG_DFX_IGU_EGU] = {"dfx_igu_egu_regs", dfx_igu_egu_regs,
+				  ARRAY_SIZE(dfx_igu_egu_regs)},
+	[HNS3_TAG_DFX_RPU_0] = {"dfx_rpu_0_regs", dfx_rpu_0_regs,
+				ARRAY_SIZE(dfx_rpu_0_regs)},
+	[HNS3_TAG_DFX_RPU_1] = {"dfx_rpu_1_regs", dfx_rpu_1_regs,
+				ARRAY_SIZE(dfx_rpu_1_regs)},
+	[HNS3_TAG_DFX_NCSI] = {"dfx_ncsi_regs", dfx_ncsi_regs,
+			       ARRAY_SIZE(dfx_ncsi_regs)},
+	[HNS3_TAG_DFX_RTC] = {"dfx_rtc_regs", dfx_rtc_regs,
+			      ARRAY_SIZE(dfx_rtc_regs)},
+	[HNS3_TAG_DFX_PPP] = {"dfx_ppp_regs", dfx_ppp_regs,
+			      ARRAY_SIZE(dfx_ppp_regs)},
+	[HNS3_TAG_DFX_RCB] = {"dfx_rcb_regs", dfx_rcb_regs,
+			      ARRAY_SIZE(dfx_rcb_regs)},
+	[HNS3_TAG_DFX_TQP] = {"dfx_tqp_regs", dfx_tqp_regs,
+			      ARRAY_SIZE(dfx_tqp_regs)},
+	[HNS3_TAG_DFX_SSU_2] = {"dfx_ssu_2_regs", dfx_ssu_2_regs,
+				ARRAY_SIZE(dfx_ssu_2_regs)},
+	[HNS3_TAG_DFX_RPU_TNL] = {"dfx_rpu_tnl", dfx_rpu_0_regs,
+				  ARRAY_SIZE(dfx_rpu_0_regs)},
+};
+
+const struct hns3_regs_group vf_regs_groups[] = {
+	[HNS3_TAG_CMDQ] = {"cmdq_regs", vf_cmdq_regs, ARRAY_SIZE(vf_cmdq_regs)},
+	[HNS3_TAG_COMMON] = {"common_regs", vf_common_regs,
+			     ARRAY_SIZE(vf_common_regs)},
+	[HNS3_TAG_RING] = {"ring_regs", vf_ring_regs, ARRAY_SIZE(vf_ring_regs)},
+	[HNS3_TAG_TQP_INTR] = {"tqp_intr_regs", vf_tqp_intr_regs,
+			       ARRAY_SIZE(vf_tqp_intr_regs)},
+};
+
+static void hns3_dump_reg_hex(const char *regs_name, const u8 *regs_data,
+			     u16 value_len, u32 name_max_len)
+{
+	if (strcmp(regs_name, HNS3_REG_RSV_NAME) == 0)
+		return;
+
+	fprintf(stdout, "  %-*s : ", name_max_len, regs_name);
+	if (value_len == 4) /* 4 bytes register */
+		fprintf(stdout, "0x%08x\n", *(u32 *)regs_data);
+	if (value_len == 8) /* 8 bytes register */
+		fprintf(stdout, "0x%016llx\n", *(u64 *)regs_data);
+}
+
+static u32 hns3_get_group_regs_name_max_len(const struct hns3_regs_group *group)
+{
+	const struct hns3_reg_info *reg;
+	u32 max_len = 0;
+	u16 i;
+
+	for (i = 0; i < group->regs_count; i++) {
+		reg = &group->regs[i];
+		max_len = strlen(reg->name) > max_len ?
+			  strlen(reg->name) : max_len;
+	}
+
+	return max_len;
+}
+
+static const char *hns3_get_group_name(const struct hns3_regs_group *group,
+				       u32 tag)
+{
+	static u32 pre_tag = HNS3_TAG_MAX;
+	static char group_name[256];
+	static u32 index;
+
+	if (!hns3_reg_is_repeat_tag_array[tag])
+		return group->group_name;
+
+	if (tag != pre_tag)
+		index = 0;
+
+	pre_tag = tag;
+	sprintf(group_name, "%s_%u", group->group_name, index++);
+	return group_name;
+}
+
+static void hns3_dump_reg_group(const struct hns3_regs_group *group, u32 tag,
+			       u32 expected_len, const u8 *regs_data)
+{
+	u32 name_max_len = hns3_get_group_regs_name_max_len(group);
+	const struct hns3_reg_info *reg;
+	u32 dump_offset = 0;
+	u16 i;
+
+	fprintf(stdout, "[%s]\n", hns3_get_group_name(group, tag));
+	for (i = 0; i < group->regs_count && dump_offset < expected_len; i++) {
+		reg = &group->regs[i];
+		hns3_dump_reg_hex(reg->name, regs_data + dump_offset,
+				  reg->value_len, name_max_len);
+		dump_offset += reg->value_len;
+	}
+
+	/* the driver may add new register.
+	 * In this case, the register name is unknown.
+	 * The register can be parsed as unknown:value format.
+	 */
+	while (dump_offset < expected_len) {
+		hns3_dump_reg_hex(HNS3_REG_UNKNOW_NAME, regs_data + dump_offset,
+				  HNS3_REG_UNKNOW_VALUE_LEN, name_max_len);
+		dump_offset += HNS3_REG_UNKNOW_VALUE_LEN;
+	}
+}
+
+static void hns3_dump_as_groups(const struct hns3_regs_group *groups,
+				const u8 *regs_data, u32 regs_len)
+{
+	u32 tlv_size = sizeof(struct hns3_reg_tlv);
+	const struct hns3_reg_tlv *tlv;
+	u32 dump_offset = 0;
+
+	while (dump_offset < regs_len) {
+		tlv = (const struct hns3_reg_tlv *)(regs_data + dump_offset);
+		hns3_dump_reg_group(&groups[tlv->tag], tlv->tag,
+				    tlv->len - tlv_size,
+				    regs_data + dump_offset + tlv_size);
+		dump_offset += tlv->len;
+	}
+}
+
+static bool hns3_dump_validate(const u8 *regs_data, u32 regs_len)
+{
+	u32 tlv_size = sizeof(struct hns3_reg_tlv);
+	const struct hns3_reg_tlv *tlv;
+	u32 dump_offset = 0;
+
+	while (dump_offset < regs_len) {
+		tlv = (const struct hns3_reg_tlv *)(regs_data + dump_offset);
+
+		/* register value length is 4 bytes or 8 bytes */
+		if ((tlv->len - tlv_size) % 4)
+			return false;
+
+		if (tlv->tag >= HNS3_TAG_MAX)
+			return false;
+
+		dump_offset += tlv->len;
+	}
+
+	return dump_offset == regs_len;
+}
+
+int hns3_dump_regs(struct ethtool_drvinfo *info __maybe_unused,
+		   struct ethtool_regs *regs)
+{
+	const struct hns3_regs_group *groups = pf_regs_groups;
+	u32 header_len = sizeof(struct hns3_reg_header);
+	const struct hns3_reg_header *header;
+
+	/* must contain header and register data */
+	if (regs->len <= header_len)
+		return -ENODATA;
+
+	header = (struct hns3_reg_header *)regs->data;
+	if (header->magic_number != HNS3_REG_MAGIC_NUMBER)
+		return -EOPNOTSUPP;
+
+	if (!hns3_dump_validate(regs->data + header_len,
+				regs->len - header_len))
+		return -EINVAL;
+
+	if (header->is_vf)
+		groups = vf_regs_groups;
+
+	hns3_dump_as_groups(groups, regs->data + header_len,
+			    regs->len - header_len);
+	return 0;
+}
diff --git a/internal.h b/internal.h
index b80f77a..4b994f5 100644
--- a/internal.h
+++ b/internal.h
@@ -21,6 +21,9 @@
 #include <unistd.h>
 #include <endian.h>
 #include <sys/ioctl.h>
+#define __UAPI_DEF_IF_IFNAMSIZ	1
+#define __UAPI_DEF_IF_IFMAP	1
+#define __UAPI_DEF_IF_IFREQ	1
 #include <linux/if.h>
 
 #include "json_writer.h"
@@ -33,29 +36,12 @@
 struct nl_context;
 #endif
 
-/* ethtool.h expects these to be defined by <linux/types.h> */
-#ifndef HAVE_BE_TYPES
-typedef uint16_t __be16;
-typedef uint32_t __be32;
-typedef unsigned long long __be64;
-#endif
-
 typedef unsigned long long u64;
 typedef uint32_t u32;
 typedef uint16_t u16;
 typedef uint8_t u8;
 typedef int32_t s32;
 
-/* ethtool.h epxects __KERNEL_DIV_ROUND_UP to be defined by <linux/kernel.h> */
-#include <linux/kernel.h>
-#ifndef __KERNEL_DIV_ROUND_UP
-#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
-#endif
-
-#ifndef ALTIFNAMSIZ
-#define ALTIFNAMSIZ 128
-#endif
-
 #include <linux/ethtool.h>
 #include <linux/net_tstamp.h>
 
@@ -374,6 +360,9 @@
 /* VMware vmxnet3 ethernet controller */
 int vmxnet3_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
 
+/* hns3 ethernet controller */
+int hns3_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
+
 /* Rx flow classification */
 int rxclass_parse_ruleopts(struct cmd_context *ctx,
 			   struct ethtool_rx_flow_spec *fsp, __u32 *rss_context);
diff --git a/m4/ax_append_flag.m4 b/m4/ax_append_flag.m4
new file mode 100644
index 0000000..e8c5312
--- /dev/null
+++ b/m4/ax_append_flag.m4
@@ -0,0 +1,71 @@
+# ===========================================================================
+#      https://www.gnu.org/software/autoconf-archive/ax_append_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
+#
+# DESCRIPTION
+#
+#   FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
+#   added in between.
+#
+#   If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
+#   CFLAGS) is used.  FLAGS-VARIABLE is not changed if it already contains
+#   FLAG.  If FLAGS-VARIABLE is unset in the shell, it is set to exactly
+#   FLAG.
+#
+#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 7
+
+AC_DEFUN([AX_APPEND_FLAG],
+[dnl
+AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
+AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
+AS_VAR_SET_IF(FLAGS,[
+  AS_CASE([" AS_VAR_GET(FLAGS) "],
+    [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
+    [
+     AS_VAR_APPEND(FLAGS,[" $1"])
+     AC_RUN_LOG([: FLAGS="$FLAGS"])
+    ])
+  ],
+  [
+  AS_VAR_SET(FLAGS,[$1])
+  AC_RUN_LOG([: FLAGS="$FLAGS"])
+  ])
+AS_VAR_POPDEF([FLAGS])dnl
+])dnl AX_APPEND_FLAG
diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4
new file mode 100644
index 0000000..dcabb92
--- /dev/null
+++ b/m4/ax_check_compile_flag.m4
@@ -0,0 +1,74 @@
+# ===========================================================================
+#  https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+#   Check whether the given FLAG works with the current language's compiler
+#   or gives an error.  (Warnings, however, are ignored)
+#
+#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+#   success/failure.
+#
+#   If EXTRA-FLAGS is defined, it is added to the current language's default
+#   flags (e.g. CFLAGS) when the check is done.  The check is thus made with
+#   the flags: "CFLAGS EXTRA-FLAGS FLAG".  This can for example be used to
+#   force the compiler to issue an error when a bad flag is given.
+#
+#   INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+#   macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 5
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+  ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+  _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+  AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+    [AS_VAR_SET(CACHEVAR,[yes])],
+    [AS_VAR_SET(CACHEVAR,[no])])
+  _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+  [m4_default([$2], :)],
+  [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
diff --git a/marvell.c b/marvell.c
index d3d570e..3f3aed8 100644
--- a/marvell.c
+++ b/marvell.c
@@ -31,23 +31,23 @@
 static void dump_queue(const char *name, const void *a, int rx)
 {
 	struct desc {
-		u_int32_t		ctl;
-		u_int32_t		next;
-		u_int32_t		data_lo;
-		u_int32_t		data_hi;
-		u_int32_t		status;
-		u_int32_t		timestamp;
-		u_int16_t		csum2;
-		u_int16_t		csum1;
-		u_int16_t		csum2_start;
-		u_int16_t		csum1_start;
-		u_int32_t		addr_lo;
-		u_int32_t		addr_hi;
-		u_int32_t		count_lo;
-		u_int32_t		count_hi;
-		u_int32_t               byte_count;
-		u_int32_t               csr;
-		u_int32_t               flag;
+		uint32_t		ctl;
+		uint32_t		next;
+		uint32_t		data_lo;
+		uint32_t		data_hi;
+		uint32_t		status;
+		uint32_t		timestamp;
+		uint16_t		csum2;
+		uint16_t		csum1;
+		uint16_t		csum2_start;
+		uint16_t		csum1_start;
+		uint32_t		addr_lo;
+		uint32_t		addr_hi;
+		uint32_t		count_lo;
+		uint32_t		count_hi;
+		uint32_t		byte_count;
+		uint32_t		csr;
+		uint32_t		flag;
 	};
 	const struct desc *d = a;
 
diff --git a/netlink/channels.c b/netlink/channels.c
index 894c74b..5cae227 100644
--- a/netlink/channels.c
+++ b/netlink/channels.c
@@ -37,15 +37,17 @@
 		putchar('\n');
 	printf("Channel parameters for %s:\n", nlctx->devname);
 	printf("Pre-set maximums:\n");
-	show_u32(tb[ETHTOOL_A_CHANNELS_RX_MAX], "RX:\t\t");
-	show_u32(tb[ETHTOOL_A_CHANNELS_TX_MAX], "TX:\t\t");
-	show_u32(tb[ETHTOOL_A_CHANNELS_OTHER_MAX], "Other:\t\t");
-	show_u32(tb[ETHTOOL_A_CHANNELS_COMBINED_MAX], "Combined:\t");
+	show_u32("rx-max", "RX:\t\t", tb[ETHTOOL_A_CHANNELS_RX_MAX]);
+	show_u32("tx-max", "TX:\t\t", tb[ETHTOOL_A_CHANNELS_TX_MAX]);
+	show_u32("other-max", "Other:\t\t", tb[ETHTOOL_A_CHANNELS_OTHER_MAX]);
+	show_u32("combined-max", "Combined:\t",
+		 tb[ETHTOOL_A_CHANNELS_COMBINED_MAX]);
 	printf("Current hardware settings:\n");
-	show_u32(tb[ETHTOOL_A_CHANNELS_RX_COUNT], "RX:\t\t");
-	show_u32(tb[ETHTOOL_A_CHANNELS_TX_COUNT], "TX:\t\t");
-	show_u32(tb[ETHTOOL_A_CHANNELS_OTHER_COUNT], "Other:\t\t");
-	show_u32(tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT], "Combined:\t");
+	show_u32("rx", "RX:\t\t", tb[ETHTOOL_A_CHANNELS_RX_COUNT]);
+	show_u32("tx", "TX:\t\t", tb[ETHTOOL_A_CHANNELS_TX_COUNT]);
+	show_u32("other", "Other:\t\t", tb[ETHTOOL_A_CHANNELS_OTHER_COUNT]);
+	show_u32("combined", "Combined:\t",
+		 tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT]);
 
 	return MNL_CB_OK;
 }
diff --git a/netlink/coalesce.c b/netlink/coalesce.c
index 15037c2..bc34d3d 100644
--- a/netlink/coalesce.c
+++ b/netlink/coalesce.c
@@ -33,43 +33,71 @@
 	if (!dev_ok(nlctx))
 		return err_ret;
 
+	open_json_object(NULL);
+
 	if (silent)
-		putchar('\n');
-	printf("Coalesce parameters for %s:\n", nlctx->devname);
+		show_cr();
+	print_string(PRINT_ANY, "ifname", "Coalesce parameters for %s:\n",
+		     nlctx->devname);
 	show_bool("rx", "Adaptive RX: %s  ",
 		  tb[ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX]);
 	show_bool("tx", "TX: %s\n", tb[ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX]);
-	show_u32(tb[ETHTOOL_A_COALESCE_STATS_BLOCK_USECS],
-		 "stats-block-usecs: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL],
-		 "sample-interval: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_PKT_RATE_LOW], "pkt-rate-low: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_PKT_RATE_HIGH], "pkt-rate-high: ");
-	putchar('\n');
-	show_u32(tb[ETHTOOL_A_COALESCE_RX_USECS], "rx-usecs: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_RX_MAX_FRAMES], "rx-frames: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_RX_USECS_IRQ], "rx-usecs-irq: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ], "rx-frames-irq: ");
-	putchar('\n');
-	show_u32(tb[ETHTOOL_A_COALESCE_TX_USECS], "tx-usecs: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_TX_MAX_FRAMES], "tx-frames: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_TX_USECS_IRQ], "tx-usecs-irq: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ], "tx-frames-irq: ");
-	putchar('\n');
-	show_u32(tb[ETHTOOL_A_COALESCE_RX_USECS_LOW], "rx-usecs-low: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW], "rx-frame-low: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_TX_USECS_LOW], "tx-usecs-low: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW], "tx-frame-low: ");
-	putchar('\n');
-	show_u32(tb[ETHTOOL_A_COALESCE_RX_USECS_HIGH], "rx-usecs-high: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH], "rx-frame-high: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_TX_USECS_HIGH], "tx-usecs-high: ");
-	show_u32(tb[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH], "tx-frame-high: ");
-	putchar('\n');
+	show_u32("stats-block-usecs", "stats-block-usecs:\t",
+		 tb[ETHTOOL_A_COALESCE_STATS_BLOCK_USECS]);
+	show_u32("sample-interval", "sample-interval:\t",
+		 tb[ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL]);
+	show_u32("pkt-rate-low", "pkt-rate-low:\t\t",
+		 tb[ETHTOOL_A_COALESCE_PKT_RATE_LOW]);
+	show_u32("pkt-rate-high", "pkt-rate-high:\t\t",
+		 tb[ETHTOOL_A_COALESCE_PKT_RATE_HIGH]);
+	show_cr();
+	show_u32("rx-usecs", "rx-usecs:\t", tb[ETHTOOL_A_COALESCE_RX_USECS]);
+	show_u32("rx-frames", "rx-frames:\t",
+		 tb[ETHTOOL_A_COALESCE_RX_MAX_FRAMES]);
+	show_u32("rx-usecs-irq", "rx-usecs-irq:\t",
+		 tb[ETHTOOL_A_COALESCE_RX_USECS_IRQ]);
+	show_u32("rx-frames-irq", "rx-frames-irq:\t",
+		 tb[ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ]);
+	show_cr();
+	show_u32("tx-usecs", "tx-usecs:\t", tb[ETHTOOL_A_COALESCE_TX_USECS]);
+	show_u32("tx-frames", "tx-frames:\t",
+		 tb[ETHTOOL_A_COALESCE_TX_MAX_FRAMES]);
+	show_u32("tx-usecs-irq", "tx-usecs-irq:\t",
+		 tb[ETHTOOL_A_COALESCE_TX_USECS_IRQ]);
+	show_u32("tx-frames-irq", "tx-frames-irq:\t",
+		 tb[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ]);
+	show_cr();
+	show_u32("rx-usecs-low", "rx-usecs-low:\t",
+		 tb[ETHTOOL_A_COALESCE_RX_USECS_LOW]);
+	show_u32("rx-frame-low", "rx-frame-low:\t",
+		 tb[ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW]);
+	show_u32("tx-usecs-low", "tx-usecs-low:\t",
+		 tb[ETHTOOL_A_COALESCE_TX_USECS_LOW]);
+	show_u32("tx-frame-low", "tx-frame-low:\t",
+		 tb[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW]);
+	show_cr();
+	show_u32("rx-usecs-high", "rx-usecs-high:\t",
+		 tb[ETHTOOL_A_COALESCE_RX_USECS_HIGH]);
+	show_u32("rx-frame-high", "rx-frame-high:\t",
+		 tb[ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH]);
+	show_u32("tx-usecs-high", "tx-usecs-high:\t",
+		 tb[ETHTOOL_A_COALESCE_TX_USECS_HIGH]);
+	show_u32("tx-frame-high", "tx-frame-high:\t",
+		 tb[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH]);
+	show_cr();
 	show_bool("rx", "CQE mode RX: %s  ",
 		  tb[ETHTOOL_A_COALESCE_USE_CQE_MODE_RX]);
 	show_bool("tx", "TX: %s\n", tb[ETHTOOL_A_COALESCE_USE_CQE_MODE_TX]);
-	putchar('\n');
+	show_cr();
+	show_u32("tx-aggr-max-bytes", "tx-aggr-max-bytes:\t",
+		 tb[ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES]);
+	show_u32("tx-aggr-max-frames", "tx-aggr-max-frames:\t",
+		 tb[ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES]);
+	show_u32("tx-aggr-time-usecs", "tx-aggr-time-usecs\t",
+		 tb[ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS]);
+	show_cr();
+
+	close_json_object();
 
 	return MNL_CB_OK;
 }
@@ -92,7 +120,11 @@
 				      ETHTOOL_A_COALESCE_HEADER, 0);
 	if (ret < 0)
 		return ret;
-	return nlsock_send_get_request(nlsk, coalesce_reply_cb);
+
+	new_json_obj(ctx->json);
+	ret = nlsock_send_get_request(nlsk, coalesce_reply_cb);
+	delete_json_obj();
+	return ret;
 }
 
 /* COALESCE_SET */
@@ -242,6 +274,24 @@
 		.handler	= nl_parse_u8bool,
 		.min_argc	= 1,
 	},
+	{
+		.arg		= "tx-aggr-max-bytes",
+		.type		= ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx-aggr-max-frames",
+		.type		= ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx-aggr-time-usecs",
+		.type		= ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
 	{}
 };
 
diff --git a/netlink/desc-ethtool.c b/netlink/desc-ethtool.c
index b3ac64d..661de26 100644
--- a/netlink/desc-ethtool.c
+++ b/netlink/desc-ethtool.c
@@ -158,6 +158,9 @@
 	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),
+	NLATTR_DESC_U32(ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN),
+	NLATTR_DESC_U32(ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX),
 };
 
 static const struct pretty_nla_desc __channels_desc[] = {
@@ -200,6 +203,9 @@
 	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL),
 	NLATTR_DESC_BOOL(ETHTOOL_A_COALESCE_USE_CQE_MODE_TX),
 	NLATTR_DESC_BOOL(ETHTOOL_A_COALESCE_USE_CQE_MODE_RX),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS),
 };
 
 static const struct pretty_nla_desc __pause_stats_desc[] = {
@@ -442,6 +448,54 @@
 	NLATTR_DESC_U32_ENUM(ETHTOOL_A_PODL_PSE_PW_D_STATUS, pse_pw_d_status),
 };
 
+static const struct pretty_nla_desc __rss_desc[] = {
+	NLATTR_DESC_INVALID(ETHTOOL_A_RSS_UNSPEC),
+	NLATTR_DESC_NESTED(ETHTOOL_A_RSS_HEADER, header),
+	NLATTR_DESC_U32(ETHTOOL_A_RSS_CONTEXT),
+	NLATTR_DESC_U32(ETHTOOL_A_RSS_HFUNC),
+	NLATTR_DESC_BINARY(ETHTOOL_A_RSS_INDIR),
+	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),
@@ -481,6 +535,12 @@
 	NLMSG_DESC(ETHTOOL_MSG_MODULE_SET, module),
 	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);
@@ -524,6 +584,12 @@
 	NLMSG_DESC(ETHTOOL_MSG_MODULE_GET_REPLY, module),
 	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 1bb580a..e2d6b71 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -47,6 +47,14 @@
 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);
+int nl_gpse(struct cmd_context *ctx);
+int nl_spse(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
 
@@ -114,6 +122,14 @@
 #define nl_getmodule		NULL
 #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
+#define nl_gpse			NULL
+#define nl_spse			NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/features.c b/netlink/features.c
index a4dae8f..5711ff4 100644
--- a/netlink/features.c
+++ b/netlink/features.c
@@ -266,7 +266,7 @@
 
 struct sfeatures_context {
 	bool			nothing_changed;
-	uint32_t		req_mask[0];
+	uint32_t		req_mask[];
 };
 
 static int find_feature(const char *name,
@@ -534,24 +534,36 @@
 	nlctx->devname = ctx->devname;
 	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_FEATURES_SET,
 		       NLM_F_REQUEST | NLM_F_ACK);
-	if (ret < 0)
+	if (ret < 0) {
+		free(sfctx);
 		return 2;
+	}
 	if (ethnla_fill_header(msgbuff, ETHTOOL_A_FEATURES_HEADER, ctx->devname,
-			       ETHTOOL_FLAG_COMPACT_BITSETS))
+			       ETHTOOL_FLAG_COMPACT_BITSETS)) {
+		free(sfctx);
 		return -EMSGSIZE;
+	}
 	ret = fill_sfeatures_bitmap(nlctx, feature_names);
-	if (ret < 0)
+	if (ret < 0) {
+		free(sfctx);
 		return ret;
+	}
 
 	ret = nlsock_sendmsg(nlsk, NULL);
-	if (ret < 0)
+	if (ret < 0) {
+		free(sfctx);
 		return 92;
+	}
 	ret = nlsock_process_reply(nlsk, sfeatures_reply_cb, nlctx);
 	if (sfctx->nothing_changed) {
 		fprintf(stderr, "Could not change any device features\n");
+		free(sfctx);
 		return nlctx->exit_code ?: 1;
 	}
-	if (ret == 0)
+	if (ret == 0) {
+		free(sfctx);
 		return 0;
+	}
+	free(sfctx);
 	return nlctx->exit_code ?: 92;
 }
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/netlink.h b/netlink/netlink.h
index f43c1bf..1274a3b 100644
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -100,12 +100,20 @@
 		    const char *between, const char *after,
 		    const char *if_none);
 
-static inline void show_u32(const struct nlattr *attr, const char *label)
+static inline void show_u32(const char *key,
+			    const char *fmt,
+			    const struct nlattr *attr)
 {
-	if (attr)
-		printf("%s%u\n", label, mnl_attr_get_u32(attr));
-	else
-		printf("%sn/a\n", label);
+	if (is_json_context()) {
+		if (attr)
+			print_uint(PRINT_JSON, key, NULL,
+				   mnl_attr_get_u32(attr));
+	} else {
+		if (attr)
+			printf("%s%u\n", fmt, mnl_attr_get_u32(attr));
+		else
+			printf("%sn/a\n", fmt);
+	}
 }
 
 static inline const char *u8_to_bool(const uint8_t *val)
@@ -120,7 +128,7 @@
 {
 	if (is_json_context()) {
 		if (val)
-			print_bool(PRINT_JSON, key, NULL, val);
+			print_bool(PRINT_JSON, key, NULL, *val);
 	} else {
 		print_string(PRINT_FP, NULL, fmt, u8_to_bool(val));
 	}
@@ -132,6 +140,12 @@
 	show_bool_val(key, fmt, attr ? mnl_attr_get_payload(attr) : NULL);
 }
 
+static inline void show_cr(void)
+{
+	if (!is_json_context())
+		putchar('\n');
+}
+
 /* misc */
 
 static inline void copy_devname(char *dst, const char *src)
diff --git a/netlink/parser.c b/netlink/parser.c
index f982f22..6f86361 100644
--- a/netlink/parser.c
+++ b/netlink/parser.c
@@ -237,7 +237,7 @@
 			 struct nl_msg_buff *msgbuff, void *dest)
 {
 	const char *arg = *nlctx->argp;
-	float meters;
+	float meters = 0.0;
 	uint32_t cm;
 	int ret;
 
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 @@
 	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 @@
 
 	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 @@
 	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/pse-pd.c b/netlink/pse-pd.c
new file mode 100644
index 0000000..d6faff8
--- /dev/null
+++ b/netlink/pse-pd.c
@@ -0,0 +1,193 @@
+/*
+ * pse.c - netlink implementation of pse commands
+ *
+ * Implementation of "ethtool --show-pse <dev>" and
+ * "ethtool --set-pse <dev> ..."
+ */
+
+#include <errno.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+#include "parser.h"
+
+/* PSE_GET */
+
+static const char *podl_pse_admin_state_name(u32 val)
+{
+	switch (val) {
+	case ETHTOOL_PODL_PSE_ADMIN_STATE_UNKNOWN:
+		return "unknown";
+	case ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED:
+		return "disabled";
+	case ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED:
+		return "enabled";
+	default:
+		return "unsupported";
+	}
+}
+
+static const char *podl_pse_pw_d_status_name(u32 val)
+{
+	switch (val) {
+	case ETHTOOL_PODL_PSE_PW_D_STATUS_UNKNOWN:
+		return "unknown";
+	case ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED:
+		return "disabled";
+	case ETHTOOL_PODL_PSE_PW_D_STATUS_SEARCHING:
+		return "searching";
+	case ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING:
+		return "delivering power";
+	case ETHTOOL_PODL_PSE_PW_D_STATUS_SLEEP:
+		return "sleep";
+	case ETHTOOL_PODL_PSE_PW_D_STATUS_IDLE:
+		return "idle";
+	case ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR:
+		return "error";
+	default:
+		return "unsupported";
+	}
+}
+
+int pse_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[ETHTOOL_A_PSE_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_PSE_HEADER]);
+	if (!dev_ok(nlctx))
+		return err_ret;
+
+	if (silent)
+		print_nl();
+
+	open_json_object(NULL);
+
+	print_string(PRINT_ANY, "ifname", "PSE attributes for %s:\n",
+		     nlctx->devname);
+
+	if (tb[ETHTOOL_A_PODL_PSE_ADMIN_STATE]) {
+		u32 val;
+
+		val = mnl_attr_get_u32(tb[ETHTOOL_A_PODL_PSE_ADMIN_STATE]);
+		print_string(PRINT_ANY, "podl-pse-admin-state",
+			     "PoDL PSE Admin State: %s\n",
+			     podl_pse_admin_state_name(val));
+	}
+
+	if (tb[ETHTOOL_A_PODL_PSE_PW_D_STATUS]) {
+		u32 val;
+
+		val = mnl_attr_get_u32(tb[ETHTOOL_A_PODL_PSE_PW_D_STATUS]);
+		print_string(PRINT_ANY, "podl-pse-power-detection-status",
+			     "PoDL PSE Power Detection Status: %s\n",
+			     podl_pse_pw_d_status_name(val));
+	}
+
+	close_json_object();
+
+	return MNL_CB_OK;
+}
+
+int nl_gpse(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_socket *nlsk;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_PSE_GET, true))
+		return -EOPNOTSUPP;
+	if (ctx->argc > 0) {
+		fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+			*ctx->argp);
+		return 1;
+	}
+
+	nlsk = nlctx->ethnl_socket;
+	ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_PSE_GET,
+				      ETHTOOL_A_PSE_HEADER, 0);
+	if (ret < 0)
+		return ret;
+
+	new_json_obj(ctx->json);
+	ret = nlsock_send_get_request(nlsk, pse_reply_cb);
+	delete_json_obj();
+
+	return ret;
+}
+
+/* PSE_SET */
+
+static const struct lookup_entry_u32 podl_pse_admin_control_values[] = {
+	{ .arg = "enable",	.val = ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED },
+	{ .arg = "disable",	.val = ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED },
+	{}
+};
+
+static const struct param_parser spse_params[] = {
+	{
+		.arg		= "podl-pse-admin-control",
+		.type		= ETHTOOL_A_PODL_PSE_ADMIN_CONTROL,
+		.handler	= nl_parse_lookup_u32,
+		.handler_data	= podl_pse_admin_control_values,
+		.min_argc	= 1,
+	},
+	{}
+};
+
+int nl_spse(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_PSE_SET, false))
+		return -EOPNOTSUPP;
+	if (!ctx->argc) {
+		fprintf(stderr, "ethtool (--set-pse): parameters missing\n");
+		return 1;
+	}
+
+	nlctx->cmd = "--set-pse";
+	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_PSE_SET,
+		       NLM_F_REQUEST | NLM_F_ACK);
+	if (ret < 0)
+		return 2;
+	if (ethnla_fill_header(msgbuff, ETHTOOL_A_PSE_HEADER,
+			       ctx->devname, 0))
+		return -EMSGSIZE;
+
+	ret = nl_parser(nlctx, spse_params, NULL, PARSER_GROUP_NONE, NULL);
+	if (ret < 0)
+		return 1;
+
+	ret = nlsock_sendmsg(nlsk, NULL);
+	if (ret < 0)
+		return 83;
+	ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
+	if (ret == 0)
+		return 0;
+	else
+		return nlctx->exit_code ?: 83;
+}
diff --git a/netlink/rings.c b/netlink/rings.c
index 6284035..51d28c2 100644
--- a/netlink/rings.c
+++ b/netlink/rings.c
@@ -21,6 +21,9 @@
 	DECLARE_ATTR_TB_INFO(tb);
 	struct nl_context *nlctx = data;
 	unsigned char tcp_hds;
+	char *tcp_hds_fmt;
+	char *tcp_hds_key;
+	char tcp_hds_buf[256];
 	bool silent;
 	int err_ret;
 	int ret;
@@ -34,41 +37,55 @@
 	if (!dev_ok(nlctx))
 		return err_ret;
 
-	if (silent)
-		putchar('\n');
-	printf("Ring parameters for %s:\n", nlctx->devname);
-	printf("Pre-set maximums:\n");
-	show_u32(tb[ETHTOOL_A_RINGS_RX_MAX], "RX:\t\t");
-	show_u32(tb[ETHTOOL_A_RINGS_RX_MINI_MAX], "RX Mini:\t");
-	show_u32(tb[ETHTOOL_A_RINGS_RX_JUMBO_MAX], "RX Jumbo:\t");
-	show_u32(tb[ETHTOOL_A_RINGS_TX_MAX], "TX:\t\t");
-	printf("Current hardware settings:\n");
-	show_u32(tb[ETHTOOL_A_RINGS_RX], "RX:\t\t");
-	show_u32(tb[ETHTOOL_A_RINGS_RX_MINI], "RX Mini:\t");
-	show_u32(tb[ETHTOOL_A_RINGS_RX_JUMBO], "RX Jumbo:\t");
-	show_u32(tb[ETHTOOL_A_RINGS_TX], "TX:\t\t");
-	show_u32(tb[ETHTOOL_A_RINGS_RX_BUF_LEN], "RX Buf Len:\t\t");
-	show_u32(tb[ETHTOOL_A_RINGS_CQE_SIZE], "CQE Size:\t\t");
-	show_bool("tx-push", "TX Push:\t%s\n", tb[ETHTOOL_A_RINGS_TX_PUSH]);
+	open_json_object(NULL);
 
+	if (silent)
+		show_cr();
+	print_string(PRINT_ANY, "ifname", "Ring parameters for %s:\n",
+		     nlctx->devname);
+	print_string(PRINT_FP, NULL, "Pre-set maximums:\n", NULL);
+	show_u32("rx-max", "RX:\t\t\t", tb[ETHTOOL_A_RINGS_RX_MAX]);
+	show_u32("rx-mini-max", "RX Mini:\t\t", tb[ETHTOOL_A_RINGS_RX_MINI_MAX]);
+	show_u32("rx-jumbo-max", "RX Jumbo:\t\t",
+		 tb[ETHTOOL_A_RINGS_RX_JUMBO_MAX]);
+	show_u32("tx-max", "TX:\t\t\t", tb[ETHTOOL_A_RINGS_TX_MAX]);
+	show_u32("tx-push-buff-max-len", "TX push buff len:\t",
+		 tb[ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX]);
+	print_string(PRINT_FP, NULL, "Current hardware settings:\n", NULL);
+	show_u32("rx", "RX:\t\t\t", tb[ETHTOOL_A_RINGS_RX]);
+	show_u32("rx-mini", "RX Mini:\t\t", tb[ETHTOOL_A_RINGS_RX_MINI]);
+	show_u32("rx-jumbo", "RX Jumbo:\t\t", tb[ETHTOOL_A_RINGS_RX_JUMBO]);
+	show_u32("tx", "TX:\t\t\t", tb[ETHTOOL_A_RINGS_TX]);
+	show_u32("rx-buf-len", "RX Buf Len:\t\t", tb[ETHTOOL_A_RINGS_RX_BUF_LEN]);
+	show_u32("cqe-size", "CQE Size:\t\t", tb[ETHTOOL_A_RINGS_CQE_SIZE]);
+	show_bool("tx-push", "TX Push:\t\t%s\n", tb[ETHTOOL_A_RINGS_TX_PUSH]);
+	show_bool("rx-push", "RX Push:\t\t%s\n", tb[ETHTOOL_A_RINGS_RX_PUSH]);
+	show_u32("tx-push-buf-len", "TX push buff len:\t",
+		 tb[ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN]);
+
+	tcp_hds_fmt = "TCP data split:\t\t%s\n";
+	tcp_hds_key = "tcp-data-split";
 	tcp_hds = tb[ETHTOOL_A_RINGS_TCP_DATA_SPLIT] ?
 		mnl_attr_get_u8(tb[ETHTOOL_A_RINGS_TCP_DATA_SPLIT]) : 0;
-	printf("TCP data split:\t");
 	switch (tcp_hds) {
 	case ETHTOOL_TCP_DATA_SPLIT_UNKNOWN:
-		printf("n/a\n");
+		print_string(PRINT_FP, tcp_hds_key, tcp_hds_fmt, "n/a");
 		break;
 	case ETHTOOL_TCP_DATA_SPLIT_DISABLED:
-		printf("off\n");
+		print_string(PRINT_ANY, tcp_hds_key, tcp_hds_fmt, "off");
 		break;
 	case ETHTOOL_TCP_DATA_SPLIT_ENABLED:
-		printf("on\n");
+		print_string(PRINT_ANY, tcp_hds_key, tcp_hds_fmt, "on");
 		break;
 	default:
-		printf("unknown(%d)\n", tcp_hds);
+		snprintf(tcp_hds_buf, sizeof(tcp_hds_buf),
+			 "unknown(%d)\n", tcp_hds);
+		print_string(PRINT_ANY, tcp_hds_key, tcp_hds_fmt, tcp_hds_buf);
 		break;
 	}
 
+	close_json_object();
+
 	return MNL_CB_OK;
 }
 
@@ -90,7 +107,11 @@
 				      ETHTOOL_A_RINGS_HEADER, 0);
 	if (ret < 0)
 		return ret;
-	return nlsock_send_get_request(nlsk, rings_reply_cb);
+
+	new_json_obj(ctx->json);
+	ret = nlsock_send_get_request(nlsk, rings_reply_cb);
+	delete_json_obj();
+	return ret;
 }
 
 /* RINGS_SET */
@@ -121,6 +142,12 @@
 		.min_argc	= 1,
 	},
 	{
+		.arg		= "tx-push-buf-len",
+		.type		= ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
 		.arg            = "rx-buf-len",
 		.type           = ETHTOOL_A_RINGS_RX_BUF_LEN,
 		.handler        = nl_parse_direct_u32,
@@ -138,6 +165,12 @@
 		.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/rss.c b/netlink/rss.c
new file mode 100644
index 0000000..4ad6065
--- /dev/null
+++ b/netlink/rss.c
@@ -0,0 +1,230 @@
+/*
+ * rss.c - netlink implementation of RSS context commands
+ *
+ * Implementation of "ethtool -x <dev>"
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+#include "strset.h"
+#include "parser.h"
+
+struct cb_args {
+	struct nl_context	*nlctx;
+	u32			num_rings;
+};
+
+void dump_json_rss_info(struct cmd_context *ctx, u32 *indir_table,
+			u32 indir_size, u8 *hkey, u32 hkey_size,
+			const struct stringset *hash_funcs, u8 hfunc)
+{
+	unsigned int i;
+
+	open_json_object(NULL);
+	print_string(PRINT_JSON, "ifname", NULL, ctx->devname);
+	if (indir_size) {
+		open_json_array("rss-indirection-table", NULL);
+		for (i = 0; i < indir_size; i++)
+			print_uint(PRINT_JSON, NULL, NULL, indir_table[i]);
+		close_json_array("\n");
+	}
+
+	if (hkey_size) {
+		open_json_array("rss-hash-key", NULL);
+		for (i = 0; i < hkey_size; i++)
+			print_uint(PRINT_JSON, NULL, NULL, (u8)hkey[i]);
+		close_json_array("\n");
+	}
+
+	if (hfunc) {
+		for (i = 0; i < get_count(hash_funcs); i++) {
+			if (hfunc & (1 << i)) {
+				print_string(PRINT_JSON, "rss-hash-function",
+					     NULL, get_string(hash_funcs, i));
+				break;
+			}
+		}
+	}
+
+	close_json_object();
+}
+
+int get_channels_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[ETHTOOL_A_CHANNELS_MAX + 1] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	struct cb_args *args = data;
+	struct nl_context *nlctx = args->nlctx;
+	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_CHANNELS_HEADER]);
+	if (!dev_ok(nlctx))
+		return err_ret;
+	if (tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT])
+		args->num_rings = mnl_attr_get_u32(tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT]);
+	if (tb[ETHTOOL_A_CHANNELS_RX_COUNT])
+		args->num_rings += mnl_attr_get_u32(tb[ETHTOOL_A_CHANNELS_RX_COUNT]);
+	return MNL_CB_OK;
+}
+
+int rss_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[ETHTOOL_A_RSS_MAX + 1] = {};
+	unsigned int indir_bytes = 0, hkey_bytes = 0;
+	DECLARE_ATTR_TB_INFO(tb);
+	struct cb_args *args = data;
+	struct nl_context *nlctx = args->nlctx;
+	const struct stringset *hash_funcs;
+	u32 rss_hfunc = 0, indir_size;
+	u32 *indir_table = NULL;
+	u8 *hkey = NULL;
+	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_RSS_HEADER]);
+	if (!dev_ok(nlctx))
+		return err_ret;
+
+	show_cr();
+
+	if (tb[ETHTOOL_A_RSS_HFUNC])
+		rss_hfunc = mnl_attr_get_u32(tb[ETHTOOL_A_RSS_HFUNC]);
+
+	if (tb[ETHTOOL_A_RSS_INDIR]) {
+		indir_bytes = mnl_attr_get_payload_len(tb[ETHTOOL_A_RSS_INDIR]);
+		indir_table = mnl_attr_get_payload(tb[ETHTOOL_A_RSS_INDIR]);
+	}
+
+	if (tb[ETHTOOL_A_RSS_HKEY]) {
+		hkey_bytes = mnl_attr_get_payload_len(tb[ETHTOOL_A_RSS_HKEY]);
+		hkey = mnl_attr_get_payload(tb[ETHTOOL_A_RSS_HKEY]);
+	}
+
+	/* Fetch RSS hash functions and their status and print */
+	if (!nlctx->is_monitor) {
+		ret = netlink_init_ethnl2_socket(nlctx);
+		if (ret < 0)
+			return MNL_CB_ERROR;
+	}
+	hash_funcs = global_stringset(ETH_SS_RSS_HASH_FUNCS,
+				      nlctx->ethnl2_socket);
+
+	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+	if (ret < 0)
+		return silent ? MNL_CB_OK : MNL_CB_ERROR;
+
+	nlctx->devname = get_dev_name(tb[ETHTOOL_A_RSS_HEADER]);
+	if (!dev_ok(nlctx))
+		return MNL_CB_OK;
+
+	/* Fetch ring count info into args->num_rings */
+	ret = nlsock_prep_get_request(nlctx->ethnl2_socket,
+				      ETHTOOL_MSG_CHANNELS_GET,
+				      ETHTOOL_A_CHANNELS_HEADER, 0);
+	if (ret < 0)
+		return MNL_CB_ERROR;
+
+	ret = nlsock_sendmsg(nlctx->ethnl2_socket, NULL);
+	if (ret < 0)
+		return MNL_CB_ERROR;
+
+	ret = nlsock_process_reply(nlctx->ethnl2_socket, get_channels_cb, args);
+	if (ret < 0)
+		return MNL_CB_ERROR;
+
+	indir_size = indir_bytes / sizeof(u32);
+	if (is_json_context()) {
+		dump_json_rss_info(nlctx->ctx, (u32 *)indir_table, indir_size,
+				   hkey, hkey_bytes, hash_funcs, rss_hfunc);
+	} else {
+		print_indir_table(nlctx->ctx, args->num_rings,
+				  indir_size, (u32 *)indir_table);
+		print_rss_hkey(hkey, hkey_bytes);
+		printf("RSS hash function:\n");
+		if (!rss_hfunc) {
+			printf("    Operation not supported\n");
+			return 0;
+		}
+		for (unsigned int i = 0; i < get_count(hash_funcs); i++) {
+			printf("    %s: %s\n", get_string(hash_funcs, i),
+			       (rss_hfunc & (1 << i)) ? "on" : "off");
+		}
+	}
+
+	return MNL_CB_OK;
+}
+
+/* RSS_GET */
+static const struct param_parser grss_params[] = {
+	{
+		.arg		= "context",
+		.type		= ETHTOOL_A_RSS_CONTEXT,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{}
+};
+
+int nl_grss(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_socket *nlsk = nlctx->ethnl_socket;
+	struct nl_msg_buff *msgbuff;
+	struct cb_args args = {};
+	int ret;
+
+	nlctx->cmd = "-x";
+	nlctx->argp = ctx->argp;
+	nlctx->argc = ctx->argc;
+	nlctx->devname = ctx->devname;
+	nlsk = nlctx->ethnl_socket;
+	msgbuff = &nlsk->msgbuff;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_RSS_GET, true))
+		return -EOPNOTSUPP;
+
+	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_RSS_GET,
+		       NLM_F_REQUEST | NLM_F_ACK);
+	if (ret < 0)
+		return 1;
+
+	if (ethnla_fill_header(msgbuff, ETHTOOL_A_RSS_HEADER,
+			       ctx->devname, 0))
+		return -EMSGSIZE;
+
+	ret = nl_parser(nlctx, grss_params, NULL, PARSER_GROUP_NONE, NULL);
+	if (ret < 0)
+		goto err;
+
+	ret = nlsock_sendmsg(nlsk, NULL);
+	if (ret < 0)
+		goto err;
+
+	args.nlctx = nlctx;
+	new_json_obj(ctx->json);
+	ret = nlsock_process_reply(nlsk, rss_reply_cb, &args);
+	delete_json_obj();
+
+	if (ret == 0)
+		return 0;
+err:
+	return nlctx->exit_code ?: 1;
+}
diff --git a/netlink/settings.c b/netlink/settings.c
index ea86e36..a506618 100644
--- a/netlink/settings.c
+++ b/netlink/settings.c
@@ -5,6 +5,7 @@
  */
 
 #include <errno.h>
+#include <inttypes.h>
 #include <string.h>
 #include <stdio.h>
 
@@ -165,6 +166,15 @@
 	[ETHTOOL_LINK_MODE_100baseFX_Half_BIT]		= __HALF_DUPLEX(100),
 	[ETHTOOL_LINK_MODE_100baseFX_Full_BIT]		= __REAL(100),
 	[ETHTOOL_LINK_MODE_10baseT1L_Full_BIT]		= __REAL(10),
+	[ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT]	= __REAL(800000),
+	[ETHTOOL_LINK_MODE_800000baseKR8_Full_BIT]	= __REAL(800000),
+	[ETHTOOL_LINK_MODE_800000baseDR8_Full_BIT]	= __REAL(800000),
+	[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);
 
@@ -772,6 +782,13 @@
 		}
 	}
 
+	if (tb[ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT]) {
+		uint32_t val;
+
+		val = mnl_attr_get_u32(tb[ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT]);
+		printf("\tLink Down Events: %u\n", val);
+	}
+
 	return MNL_CB_OK;
 }
 
@@ -882,12 +899,84 @@
 	return MNL_CB_OK;
 }
 
-static int gset_request(struct nl_socket *nlsk, uint8_t msg_type,
-			uint16_t hdr_attr, mnl_cb_t cb)
+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;
 
-	ret = nlsock_prep_get_request(nlsk, msg_type, hdr_attr, 0);
+	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 cmd_context *ctx, uint8_t msg_type,
+			uint16_t hdr_attr, mnl_cb_t cb)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_socket *nlsk = nlctx->ethnl_socket;
+	u32 flags;
+	int ret;
+
+	if (netlink_cmd_check(ctx, msg_type, true))
+		return 0;
+
+	flags = get_stats_flag(nlctx, msg_type, hdr_attr);
+
+	ret = nlsock_prep_get_request(nlsk, msg_type, hdr_attr, flags);
 	if (ret < 0)
 		return ret;
 	return nlsock_send_get_request(nlsk, cb);
@@ -895,10 +984,9 @@
 
 int nl_gset(struct cmd_context *ctx)
 {
-	struct nl_context *nlctx = ctx->nlctx;
-	struct nl_socket *nlsk = nlctx->ethnl_socket;
 	int ret;
 
+	/* Check for the base set of commands */
 	if (netlink_cmd_check(ctx, ETHTOOL_MSG_LINKMODES_GET, true) ||
 	    netlink_cmd_check(ctx, ETHTOOL_MSG_LINKINFO_GET, true) ||
 	    netlink_cmd_check(ctx, ETHTOOL_MSG_WOL_GET, true) ||
@@ -906,39 +994,48 @@
 	    netlink_cmd_check(ctx, ETHTOOL_MSG_LINKSTATE_GET, true))
 		return -EOPNOTSUPP;
 
-	nlctx->suppress_nlerr = 1;
+	ctx->nlctx->suppress_nlerr = 1;
 
-	ret = gset_request(nlsk, ETHTOOL_MSG_LINKMODES_GET,
+	ret = gset_request(ctx, ETHTOOL_MSG_LINKMODES_GET,
 			   ETHTOOL_A_LINKMODES_HEADER, linkmodes_reply_cb);
 	if (ret == -ENODEV)
 		return ret;
 
-	ret = gset_request(nlsk, ETHTOOL_MSG_LINKINFO_GET,
+	ret = gset_request(ctx, ETHTOOL_MSG_LINKINFO_GET,
 			   ETHTOOL_A_LINKINFO_HEADER, linkinfo_reply_cb);
 	if (ret == -ENODEV)
 		return ret;
 
-	ret = gset_request(nlsk, ETHTOOL_MSG_WOL_GET, ETHTOOL_A_WOL_HEADER,
+	ret = gset_request(ctx, ETHTOOL_MSG_WOL_GET, ETHTOOL_A_WOL_HEADER,
 			   wol_reply_cb);
 	if (ret == -ENODEV)
 		return ret;
 
-	ret = gset_request(nlsk, ETHTOOL_MSG_DEBUG_GET, ETHTOOL_A_DEBUG_HEADER,
+	ret = gset_request(ctx, ETHTOOL_MSG_PLCA_GET_CFG,
+			   ETHTOOL_A_PLCA_HEADER, plca_cfg_reply_cb);
+	if (ret == -ENODEV)
+		return ret;
+
+	ret = gset_request(ctx, ETHTOOL_MSG_DEBUG_GET, ETHTOOL_A_DEBUG_HEADER,
 			   debug_reply_cb);
 	if (ret == -ENODEV)
 		return ret;
 
-	ret = gset_request(nlsk, ETHTOOL_MSG_LINKSTATE_GET,
+	ret = gset_request(ctx, ETHTOOL_MSG_LINKSTATE_GET,
 			   ETHTOOL_A_LINKSTATE_HEADER, linkstate_reply_cb);
 	if (ret == -ENODEV)
 		return ret;
 
-	if (!nlctx->no_banner) {
+	ret = gset_request(ctx, ETHTOOL_MSG_PLCA_GET_STATUS,
+			   ETHTOOL_A_PLCA_HEADER, plca_status_reply_cb);
+	if (ret == -ENODEV)
+		return ret;
+
+	if (!ctx->nlctx->no_banner) {
 		printf("No data available\n");
 		return 75;
 	}
 
-
 	return 0;
 }
 
@@ -992,7 +1089,7 @@
 	.force_hex	= true,
 };
 
-static const struct lookup_entry_u32 duplex_values[] = {
+static const struct lookup_entry_u8 duplex_values[] = {
 	{ .arg = "half",	.val = DUPLEX_HALF },
 	{ .arg = "full",	.val = DUPLEX_FULL },
 	{}
@@ -1245,6 +1342,9 @@
 	nlctx->devname = ctx->devname;
 
 	ret = nl_parser(nlctx, sset_params, NULL, PARSER_GROUP_MSG, msgbuffs);
+	if (ret == -EOPNOTSUPP)
+		return ret;
+
 	if (ret < 0) {
 		ret = 1;
 		goto out_free;
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 @@
 	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 @@
 		.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/qsfp.c b/qsfp.c
index 1fe5de1..5a535c5 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -872,6 +872,35 @@
 	}
 }
 
+static void sff8636_show_signals(const struct sff8636_memory_map *map)
+{
+	unsigned int v;
+
+	/* There appears to be no Rx LOS support bit, use Tx for both */
+	if (map->page_00h[SFF8636_OPTION_4_OFFSET] & SFF8636_O4_TX_LOS) {
+		v = map->lower_memory[SFF8636_LOS_AW_OFFSET] & 0xf;
+		sff_show_lane_status("Rx loss of signal", 4, "Yes", "No", v);
+		v = map->lower_memory[SFF8636_LOS_AW_OFFSET] >> 4;
+		sff_show_lane_status("Tx loss of signal", 4, "Yes", "No", v);
+	}
+
+	v = map->lower_memory[SFF8636_LOL_AW_OFFSET] & 0xf;
+	if (map->page_00h[SFF8636_OPTION_3_OFFSET] & SFF8636_O3_RX_LOL)
+		sff_show_lane_status("Rx loss of lock", 4, "Yes", "No", v);
+
+	v = map->lower_memory[SFF8636_LOL_AW_OFFSET] >> 4;
+	if (map->page_00h[SFF8636_OPTION_3_OFFSET] & SFF8636_O3_TX_LOL)
+		sff_show_lane_status("Tx loss of lock", 4, "Yes", "No", v);
+
+	v = map->lower_memory[SFF8636_FAULT_AW_OFFSET] & 0xf;
+	if (map->page_00h[SFF8636_OPTION_4_OFFSET] & SFF8636_O4_TX_FAULT)
+		sff_show_lane_status("Tx fault", 4, "Yes", "No", v);
+
+	v = map->lower_memory[SFF8636_FAULT_AW_OFFSET] >> 4;
+	if (map->page_00h[SFF8636_OPTION_2_OFFSET] & SFF8636_O2_TX_EQ_AUTO)
+		sff_show_lane_status("Tx adaptive eq fault", 4, "Yes", "No", v);
+}
+
 static void sff8636_show_page_zero(const struct sff8636_memory_map *map)
 {
 	sff8636_show_ext_identifier(map);
@@ -905,6 +934,7 @@
 		       SFF8636_DATE_VENDOR_LOT_OFFSET + 1, "Date code");
 	sff_show_revision_compliance(map->lower_memory,
 				     SFF8636_REV_COMPLIANCE_OFFSET);
+	sff8636_show_signals(map);
 }
 
 static void sff8636_show_all_common(const struct sff8636_memory_map *map)
diff --git a/qsfp.h b/qsfp.h
index aabf09f..9f0cb0f 100644
--- a/qsfp.h
+++ b/qsfp.h
@@ -55,6 +55,8 @@
 #define	 SFF8636_TX2_FAULT_AW	(1 << 1)
 #define	 SFF8636_TX1_FAULT_AW	(1 << 0)
 
+#define	SFF8636_LOL_AW_OFFSET	0x05
+
 /* Module Monitor Interrupt Flags - 6-8 */
 #define	SFF8636_TEMP_AW_OFFSET	0x06
 #define	 SFF8636_TEMP_HALARM_STATUS		(1 << 7)
@@ -525,9 +527,15 @@
 /*  56h-5Fh reserved */
 
 #define	 SFF8636_OPTION_2_OFFSET	0xC1
+/* Tx input equalizers auto-adaptive */
+#define	  SFF8636_O2_TX_EQ_AUTO		(1 << 3)
 /* Rx output amplitude */
 #define	  SFF8636_O2_RX_OUTPUT_AMP	(1 << 0)
 #define	 SFF8636_OPTION_3_OFFSET	0xC2
+/* Tx CDR Loss of Lock */
+#define	  SFF8636_O3_TX_LOL		(1 << 5)
+/* Rx CDR Loss of Lock */
+#define	  SFF8636_O3_RX_LOL		(1 << 4)
 /* Rx Squelch Disable */
 #define	  SFF8636_O3_RX_SQL_DSBL	(1 << 3)
 /* Rx Output Disable capable */
diff --git a/rxclass.c b/rxclass.c
index 6cf81fd..f17e3a5 100644
--- a/rxclass.c
+++ b/rxclass.c
@@ -446,7 +446,7 @@
 	 * If loc rolls over it should be greater than or equal to rmgr->size
 	 * and as such we know we have reached the end of the list.
 	 */
-	if (!~(rmgr->slot[slot_num] | (~1UL << rmgr->size % BITS_PER_LONG))) {
+	if (!~(rmgr->slot[slot_num] | (~1UL << loc % BITS_PER_LONG))) {
 		loc -= 1 + (loc % BITS_PER_LONG);
 		slot_num--;
 	}
@@ -598,7 +598,7 @@
 	else if (loc & RX_CLS_LOC_SPECIAL)
 		printf("Added rule with ID %d\n", nfccmd.fs.location);
 
-	return 0;
+	return err;
 }
 
 int rxclass_rule_del(struct cmd_context *ctx, __u32 loc)
diff --git a/scripts/ethtool-import-uapi b/scripts/ethtool-import-uapi
new file mode 100755
index 0000000..a04a9c9
--- /dev/null
+++ b/scripts/ethtool-import-uapi
@@ -0,0 +1,67 @@
+#!/bin/bash -e
+#
+# ethtool-import-uapi [commit]
+#
+# Imports sanitized copies of kernel uapi headers from <commit> (can be
+# a commit id, a tag or a branch name). If the argument is omitted,
+# commit currently checked out in the kernel repository is used.
+
+sn="${0##*/}"
+export ARCH="x86_64"
+mkopt="-j$(nproc)" || mkopt=''
+
+if [ ! -d "$LINUX_GIT" ]; then
+    echo "${sn}: please set LINUX_GIT to the location of kernel git" >&2
+    exit 1
+fi
+
+pushd "$LINUX_GIT"
+if [ -n "$1" ]; then
+    git checkout "$1"
+fi
+desc=$(git describe --exact-match 2>/dev/null \
+       || git show -s --abbrev=12 --pretty='commit %h')
+kobj=$(mktemp -d)
+make $mkopt O="$kobj" allmodconfig
+make $mkopt O="$kobj" prepare
+make $mkopt O="$kobj" INSTALL_HDR_PATH="${kobj}/hdr" headers_install
+popd
+
+pushd uapi
+find . -type f -name '*.h' -exec cp -v "${kobj}/hdr/include/{}" {} \;
+
+go_on=true
+while $go_on; do
+    go_on=false
+    while read f; do
+        if [ "${f#asm/}" != "$f" ]; then
+            # skip architecture dependent asm/ headers
+            continue
+        fi
+        if [ -f "$f" ]; then
+            # already present
+            continue
+        fi
+	if [ ! -f "${kobj}/hdr/include/${f}" ]; then
+            # not a kernel header
+            continue
+        fi
+        echo "+ add $f"
+        go_on=true
+        mkdir -p "${f%/*}"
+        cp "${kobj}/hdr/include/${f}" "${f}"
+    done < <(
+        find . -type f -name '*.[ch]' -exec sed -nre '\_^[[:blank:]]*#include[[:blank:]]<.+>_ { s_^[[:blank:]]*#include[[:blank:]]<([^>]*)>.*$_\1_ ; p }' {} \; \
+            | LC_ALL=C sort -u
+    )
+done
+popd
+rm -rf "$kobj"
+
+git add uapi
+git commit -s -F - <<EOT
+update UAPI header copies
+
+Update to kernel ${desc}.
+
+EOT
diff --git a/sff-common.c b/sff-common.c
index e951cf1..a5c1510 100644
--- a/sff-common.c
+++ b/sff-common.c
@@ -53,6 +53,23 @@
 	printf("\n");
 }
 
+void sff_show_lane_status(const char *name, unsigned int lane_cnt,
+			  const char *yes, const char *no, unsigned int value)
+{
+	printf("\t%-41s : ", name);
+	if (!value) {
+		printf("None\n");
+		return;
+	}
+
+	printf("[");
+	while (lane_cnt--) {
+		printf(" %s%c", value & 1 ? yes : no, lane_cnt ? ',': ' ');
+		value >>= 1;
+	}
+	printf("]\n");
+}
+
 void sff8024_show_oui(const __u8 *id, int id_offset)
 {
 	printf("\t%-41s : %02x:%02x:%02x\n", "Vendor OUI",
diff --git a/sff-common.h b/sff-common.h
index dd12dda..57bcc4a 100644
--- a/sff-common.h
+++ b/sff-common.h
@@ -198,6 +198,8 @@
 			      const char *unit);
 void sff_show_ascii(const __u8 *id, unsigned int first_reg,
 		    unsigned int last_reg, const char *name);
+void sff_show_lane_status(const char *name, unsigned int lane_cnt,
+			  const char *yes, const char *no, unsigned int value);
 void sff_show_thresholds(struct sff_diags sd);
 
 void sff8024_show_oui(const __u8 *id, int id_offset);
diff --git a/shell-completion/bash/ethtool b/shell-completion/bash/ethtool
index 46334b5..99c5f6f 100644
--- a/shell-completion/bash/ethtool
+++ b/shell-completion/bash/ethtool
@@ -254,6 +254,9 @@
 		[tx-usecs-high]=1
 		[tx-usecs-irq]=1
 		[tx-usecs-low]=1
+		[tx-aggr-max-bytes]=1
+		[tx-aggr-max-frames]=1
+		[tx-aggr-time-usecs]=1
 	)
 
 	case "$prev" in
diff --git a/uapi/linux/const.h b/uapi/linux/const.h
new file mode 100644
index 0000000..1eb84b5
--- /dev/null
+++ b/uapi/linux/const.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* const.h: Macros for dealing with constants.  */
+
+#ifndef _LINUX_CONST_H
+#define _LINUX_CONST_H
+
+/* Some constant macros are used in both assembler and
+ * C code.  Therefore we cannot annotate them always with
+ * 'UL' and other type specifiers unilaterally.  We
+ * use the following macros to deal with this.
+ *
+ * Similarly, _AT() will cast an expression with a type in C, but
+ * leave it unchanged in asm.
+ */
+
+#ifdef __ASSEMBLY__
+#define _AC(X,Y)	X
+#define _AT(T,X)	X
+#else
+#define __AC(X,Y)	(X##Y)
+#define _AC(X,Y)	__AC(X,Y)
+#define _AT(T,X)	((T)(X))
+#endif
+
+#define _UL(x)		(_AC(x, UL))
+#define _ULL(x)		(_AC(x, ULL))
+
+#define _BITUL(x)	(_UL(1) << (x))
+#define _BITULL(x)	(_ULL(1) << (x))
+
+#define __ALIGN_KERNEL(x, a)		__ALIGN_KERNEL_MASK(x, (__typeof__(x))(a) - 1)
+#define __ALIGN_KERNEL_MASK(x, mask)	(((x) + (mask)) & ~(mask))
+
+#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
+#endif /* _LINUX_CONST_H */
diff --git a/uapi/linux/ethtool.h b/uapi/linux/ethtool.h
index f1f94f7..1d0731b 100644
--- a/uapi/linux/ethtool.h
+++ b/uapi/linux/ethtool.h
@@ -157,8 +157,10 @@
  *	in its bus driver structure (e.g. pci_driver::name).  Must
  *	not be an empty string.
  * @version: Driver version string; may be an empty string
- * @fw_version: Firmware version string; may be an empty string
- * @erom_version: Expansion ROM version string; may be an empty string
+ * @fw_version: Firmware version string; driver defined; may be an
+ *	empty string
+ * @erom_version: Expansion ROM version string; driver defined; may be
+ *	an empty string
  * @bus_info: Device bus address.  This should match the dev_name()
  *	string for the underlying bus device, if there is one.  May be
  *	an empty string.
@@ -177,10 +179,6 @@
  *
  * Users can use the %ETHTOOL_GSSET_INFO command to get the number of
  * strings in any string set (from Linux 2.6.34).
- *
- * Drivers should set at most @driver, @version, @fw_version and
- * @bus_info in their get_drvinfo() implementation.  The ethtool
- * core fills in the other fields using other driver operations.
  */
 struct ethtool_drvinfo {
 	__u32	cmd;
@@ -712,6 +710,24 @@
 };
 
 /**
+ * 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
@@ -780,6 +796,31 @@
 };
 
 /**
+ * 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
@@ -1183,7 +1224,7 @@
 		__u32			rule_cnt;
 		__u32			rss_context;
 	};
-	__u32				rule_locs[0];
+	__u32				rule_locs[];
 };
 
 
@@ -1735,6 +1776,16 @@
 	ETHTOOL_LINK_MODE_100baseFX_Half_BIT		 = 90,
 	ETHTOOL_LINK_MODE_100baseFX_Full_BIT		 = 91,
 	ETHTOOL_LINK_MODE_10baseT1L_Full_BIT		 = 92,
+	ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT	 = 93,
+	ETHTOOL_LINK_MODE_800000baseKR8_Full_BIT	 = 94,
+	ETHTOOL_LINK_MODE_800000baseDR8_Full_BIT	 = 95,
+	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
 };
@@ -1846,6 +1897,7 @@
 #define SPEED_100000		100000
 #define SPEED_200000		200000
 #define SPEED_400000		400000
+#define SPEED_800000		800000
 
 #define SPEED_UNKNOWN		-1
 
diff --git a/uapi/linux/ethtool_netlink.h b/uapi/linux/ethtool_netlink.h
index ed46d35..a8b0d79 100644
--- a/uapi/linux/ethtool_netlink.h
+++ b/uapi/linux/ethtool_netlink.h
@@ -51,6 +51,12 @@
 	ETHTOOL_MSG_MODULE_SET,
 	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,
@@ -97,6 +103,12 @@
 	ETHTOOL_MSG_MODULE_GET_REPLY,
 	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,
@@ -262,6 +274,7 @@
 	ETHTOOL_A_LINKSTATE_SQI_MAX,		/* u32 */
 	ETHTOOL_A_LINKSTATE_EXT_STATE,		/* u8 */
 	ETHTOOL_A_LINKSTATE_EXT_SUBSTATE,	/* u8 */
+	ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT,	/* u32 */
 
 	/* add new constants above here */
 	__ETHTOOL_A_LINKSTATE_CNT,
@@ -343,6 +356,9 @@
 	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 */
+	ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN,		/* u32 */
+	ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX,		/* u32 */
 
 	/* add new constants above here */
 	__ETHTOOL_A_RINGS_CNT,
@@ -397,6 +413,9 @@
 	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,
@@ -412,6 +431,7 @@
 	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,
@@ -728,6 +748,8 @@
 
 	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)
@@ -761,7 +783,7 @@
 
 	/* add new constants above here */
 	__ETHTOOL_A_STATS_GRP_CNT,
-	ETHTOOL_A_STATS_GRP_MAX = (__ETHTOOL_A_STATS_CNT - 1)
+	ETHTOOL_A_STATS_GRP_MAX = (__ETHTOOL_A_STATS_GRP_CNT - 1)
 };
 
 enum {
@@ -879,6 +901,80 @@
 	ETHTOOL_A_PSE_MAX = (__ETHTOOL_A_PSE_CNT - 1)
 };
 
+enum {
+	ETHTOOL_A_RSS_UNSPEC,
+	ETHTOOL_A_RSS_HEADER,
+	ETHTOOL_A_RSS_CONTEXT,		/* u32 */
+	ETHTOOL_A_RSS_HFUNC,		/* u32 */
+	ETHTOOL_A_RSS_INDIR,		/* binary */
+	ETHTOOL_A_RSS_HKEY,		/* binary */
+
+	__ETHTOOL_A_RSS_CNT,
+	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/hdlc/ioctl.h b/uapi/linux/hdlc/ioctl.h
new file mode 100644
index 0000000..b06341a
--- /dev/null
+++ b/uapi/linux/hdlc/ioctl.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __HDLC_IOCTL_H__
+#define __HDLC_IOCTL_H__
+
+
+#define GENERIC_HDLC_VERSION 4	/* For synchronization with sethdlc utility */
+
+#define CLOCK_DEFAULT   0	/* Default setting */
+#define CLOCK_EXT	1	/* External TX and RX clock - DTE */
+#define CLOCK_INT	2	/* Internal TX and RX clock - DCE */
+#define CLOCK_TXINT	3	/* Internal TX and external RX clock */
+#define CLOCK_TXFROMRX	4	/* TX clock derived from external RX clock */
+
+
+#define ENCODING_DEFAULT	0 /* Default setting */
+#define ENCODING_NRZ		1
+#define ENCODING_NRZI		2
+#define ENCODING_FM_MARK	3
+#define ENCODING_FM_SPACE	4
+#define ENCODING_MANCHESTER	5
+
+
+#define PARITY_DEFAULT		0 /* Default setting */
+#define PARITY_NONE		1 /* No parity */
+#define PARITY_CRC16_PR0	2 /* CRC16, initial value 0x0000 */
+#define PARITY_CRC16_PR1	3 /* CRC16, initial value 0xFFFF */
+#define PARITY_CRC16_PR0_CCITT	4 /* CRC16, initial 0x0000, ITU-T version */
+#define PARITY_CRC16_PR1_CCITT	5 /* CRC16, initial 0xFFFF, ITU-T version */
+#define PARITY_CRC32_PR0_CCITT	6 /* CRC32, initial value 0x00000000 */
+#define PARITY_CRC32_PR1_CCITT	7 /* CRC32, initial value 0xFFFFFFFF */
+
+#define LMI_DEFAULT		0 /* Default setting */
+#define LMI_NONE		1 /* No LMI, all PVCs are static */
+#define LMI_ANSI		2 /* ANSI Annex D */
+#define LMI_CCITT		3 /* ITU-T Annex A */
+#define LMI_CISCO		4 /* The "original" LMI, aka Gang of Four */
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+	unsigned int clock_rate; /* bits per second */
+	unsigned int clock_type; /* internal, external, TX-internal etc. */
+	unsigned short loopback;
+} sync_serial_settings;          /* V.35, V.24, X.21 */
+
+typedef struct {
+	unsigned int clock_rate; /* bits per second */
+	unsigned int clock_type; /* internal, external, TX-internal etc. */
+	unsigned short loopback;
+	unsigned int slot_map;
+} te1_settings;                  /* T1, E1 */
+
+typedef struct {
+	unsigned short encoding;
+	unsigned short parity;
+} raw_hdlc_proto;
+
+typedef struct {
+	unsigned int t391;
+	unsigned int t392;
+	unsigned int n391;
+	unsigned int n392;
+	unsigned int n393;
+	unsigned short lmi;
+	unsigned short dce; /* 1 for DCE (network side) operation */
+} fr_proto;
+
+typedef struct {
+	unsigned int dlci;
+} fr_proto_pvc;          /* for creating/deleting FR PVCs */
+
+typedef struct {
+	unsigned int dlci;
+	char master[IFNAMSIZ];	/* Name of master FRAD device */
+}fr_proto_pvc_info;		/* for returning PVC information only */
+
+typedef struct {
+    unsigned int interval;
+    unsigned int timeout;
+} cisco_proto;
+
+typedef struct {
+	unsigned short dce; /* 1 for DCE (network side) operation */
+	unsigned int modulo; /* modulo (8 = basic / 128 = extended) */
+	unsigned int window; /* frame window size */
+	unsigned int t1; /* timeout t1 */
+	unsigned int t2; /* timeout t2 */
+	unsigned int n2; /* frame retry counter */
+} x25_hdlc_proto;
+
+/* PPP doesn't need any info now - supply length = 0 to ioctl */
+
+#endif /* __ASSEMBLY__ */
+#endif /* __HDLC_IOCTL_H__ */
diff --git a/uapi/linux/if.h b/uapi/linux/if.h
new file mode 100644
index 0000000..b287b2a
--- /dev/null
+++ b/uapi/linux/if.h
@@ -0,0 +1,296 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		Global definitions for the INET interface module.
+ *
+ * Version:	@(#)if.h	1.0.2	04/18/93
+ *
+ * Authors:	Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988
+ *		Ross Biro
+ *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IF_H
+#define _LINUX_IF_H
+
+#include <linux/libc-compat.h>          /* for compatibility with glibc */
+#include <linux/types.h>		/* for "__kernel_caddr_t" et al	*/
+#include <linux/socket.h>		/* for "struct sockaddr" et al	*/
+		/* for "__user" et al           */
+
+#include <sys/socket.h>			/* for struct sockaddr.		*/
+
+#if __UAPI_DEF_IF_IFNAMSIZ
+#define	IFNAMSIZ	16
+#endif /* __UAPI_DEF_IF_IFNAMSIZ */
+#define	IFALIASZ	256
+#define	ALTIFNAMSIZ	128
+#include <linux/hdlc/ioctl.h>
+
+/* For glibc compatibility. An empty enum does not compile. */
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 || \
+    __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0
+/**
+ * enum net_device_flags - &struct net_device flags
+ *
+ * These are the &struct net_device flags, they can be set by drivers, the
+ * kernel and some can be triggered by userspace. Userspace can query and
+ * set these flags using userspace utilities but there is also a sysfs
+ * entry available for all dev flags which can be queried and set. These flags
+ * are shared for all types of net_devices. The sysfs entries are available
+ * via /sys/class/net/<dev>/flags. Flags which can be toggled through sysfs
+ * are annotated below, note that only a few flags can be toggled and some
+ * other flags are always preserved from the original net_device flags
+ * even if you try to set them via sysfs. Flags which are always preserved
+ * are kept under the flag grouping @IFF_VOLATILE. Flags which are __volatile__
+ * are annotated below as such.
+ *
+ * You should have a pretty good reason to be extending these flags.
+ *
+ * @IFF_UP: interface is up. Can be toggled through sysfs.
+ * @IFF_BROADCAST: broadcast address valid. Volatile.
+ * @IFF_DEBUG: turn on debugging. Can be toggled through sysfs.
+ * @IFF_LOOPBACK: is a loopback net. Volatile.
+ * @IFF_POINTOPOINT: interface is has p-p link. Volatile.
+ * @IFF_NOTRAILERS: avoid use of trailers. Can be toggled through sysfs.
+ *	Volatile.
+ * @IFF_RUNNING: interface RFC2863 OPER_UP. Volatile.
+ * @IFF_NOARP: no ARP protocol. Can be toggled through sysfs. Volatile.
+ * @IFF_PROMISC: receive all packets. Can be toggled through sysfs.
+ * @IFF_ALLMULTI: receive all multicast packets. Can be toggled through
+ *	sysfs.
+ * @IFF_MASTER: master of a load balancer. Volatile.
+ * @IFF_SLAVE: slave of a load balancer. Volatile.
+ * @IFF_MULTICAST: Supports multicast. Can be toggled through sysfs.
+ * @IFF_PORTSEL: can set media type. Can be toggled through sysfs.
+ * @IFF_AUTOMEDIA: auto media select active. Can be toggled through sysfs.
+ * @IFF_DYNAMIC: dialup device with changing addresses. Can be toggled
+ *	through sysfs.
+ * @IFF_LOWER_UP: driver signals L1 up. Volatile.
+ * @IFF_DORMANT: driver signals dormant. Volatile.
+ * @IFF_ECHO: echo sent packets. Volatile.
+ */
+enum net_device_flags {
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS
+	IFF_UP				= 1<<0,  /* sysfs */
+	IFF_BROADCAST			= 1<<1,  /* __volatile__ */
+	IFF_DEBUG			= 1<<2,  /* sysfs */
+	IFF_LOOPBACK			= 1<<3,  /* __volatile__ */
+	IFF_POINTOPOINT			= 1<<4,  /* __volatile__ */
+	IFF_NOTRAILERS			= 1<<5,  /* sysfs */
+	IFF_RUNNING			= 1<<6,  /* __volatile__ */
+	IFF_NOARP			= 1<<7,  /* sysfs */
+	IFF_PROMISC			= 1<<8,  /* sysfs */
+	IFF_ALLMULTI			= 1<<9,  /* sysfs */
+	IFF_MASTER			= 1<<10, /* __volatile__ */
+	IFF_SLAVE			= 1<<11, /* __volatile__ */
+	IFF_MULTICAST			= 1<<12, /* sysfs */
+	IFF_PORTSEL			= 1<<13, /* sysfs */
+	IFF_AUTOMEDIA			= 1<<14, /* sysfs */
+	IFF_DYNAMIC			= 1<<15, /* sysfs */
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
+	IFF_LOWER_UP			= 1<<16, /* __volatile__ */
+	IFF_DORMANT			= 1<<17, /* __volatile__ */
+	IFF_ECHO			= 1<<18, /* __volatile__ */
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
+};
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 || __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0 */
+
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS
+#define IFF_UP				IFF_UP
+#define IFF_BROADCAST			IFF_BROADCAST
+#define IFF_DEBUG			IFF_DEBUG
+#define IFF_LOOPBACK			IFF_LOOPBACK
+#define IFF_POINTOPOINT			IFF_POINTOPOINT
+#define IFF_NOTRAILERS			IFF_NOTRAILERS
+#define IFF_RUNNING			IFF_RUNNING
+#define IFF_NOARP			IFF_NOARP
+#define IFF_PROMISC			IFF_PROMISC
+#define IFF_ALLMULTI			IFF_ALLMULTI
+#define IFF_MASTER			IFF_MASTER
+#define IFF_SLAVE			IFF_SLAVE
+#define IFF_MULTICAST			IFF_MULTICAST
+#define IFF_PORTSEL			IFF_PORTSEL
+#define IFF_AUTOMEDIA			IFF_AUTOMEDIA
+#define IFF_DYNAMIC			IFF_DYNAMIC
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */
+
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
+#define IFF_LOWER_UP			IFF_LOWER_UP
+#define IFF_DORMANT			IFF_DORMANT
+#define IFF_ECHO			IFF_ECHO
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
+
+#define IFF_VOLATILE	(IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\
+		IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
+
+#define IF_GET_IFACE	0x0001		/* for querying only */
+#define IF_GET_PROTO	0x0002
+
+/* For definitions see hdlc.h */
+#define IF_IFACE_V35	0x1000		/* V.35 serial interface	*/
+#define IF_IFACE_V24	0x1001		/* V.24 serial interface	*/
+#define IF_IFACE_X21	0x1002		/* X.21 serial interface	*/
+#define IF_IFACE_T1	0x1003		/* T1 telco serial interface	*/
+#define IF_IFACE_E1	0x1004		/* E1 telco serial interface	*/
+#define IF_IFACE_SYNC_SERIAL 0x1005	/* can't be set by software	*/
+#define IF_IFACE_X21D   0x1006          /* X.21 Dual Clocking (FarSite) */
+
+/* For definitions see hdlc.h */
+#define IF_PROTO_HDLC	0x2000		/* raw HDLC protocol		*/
+#define IF_PROTO_PPP	0x2001		/* PPP protocol			*/
+#define IF_PROTO_CISCO	0x2002		/* Cisco HDLC protocol		*/
+#define IF_PROTO_FR	0x2003		/* Frame Relay protocol		*/
+#define IF_PROTO_FR_ADD_PVC 0x2004	/*    Create FR PVC		*/
+#define IF_PROTO_FR_DEL_PVC 0x2005	/*    Delete FR PVC		*/
+#define IF_PROTO_X25	0x2006		/* X.25				*/
+#define IF_PROTO_HDLC_ETH 0x2007	/* raw HDLC, Ethernet emulation	*/
+#define IF_PROTO_FR_ADD_ETH_PVC 0x2008	/*  Create FR Ethernet-bridged PVC */
+#define IF_PROTO_FR_DEL_ETH_PVC 0x2009	/*  Delete FR Ethernet-bridged PVC */
+#define IF_PROTO_FR_PVC	0x200A		/* for reading PVC status	*/
+#define IF_PROTO_FR_ETH_PVC 0x200B
+#define IF_PROTO_RAW    0x200C          /* RAW Socket                   */
+
+/* RFC 2863 operational status */
+enum {
+	IF_OPER_UNKNOWN,
+	IF_OPER_NOTPRESENT,
+	IF_OPER_DOWN,
+	IF_OPER_LOWERLAYERDOWN,
+	IF_OPER_TESTING,
+	IF_OPER_DORMANT,
+	IF_OPER_UP,
+};
+
+/* link modes */
+enum {
+	IF_LINK_MODE_DEFAULT,
+	IF_LINK_MODE_DORMANT,	/* limit upward transition to dormant */
+	IF_LINK_MODE_TESTING,	/* limit upward transition to testing */
+};
+
+/*
+ *	Device mapping structure. I'd just gone off and designed a 
+ *	beautiful scheme using only loadable modules with arguments
+ *	for driver options and along come the PCMCIA people 8)
+ *
+ *	Ah well. The get() side of this is good for WDSETUP, and it'll
+ *	be handy for debugging things. The set side is fine for now and
+ *	being very small might be worth keeping for clean configuration.
+ */
+
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_IFMAP
+struct ifmap {
+	unsigned long mem_start;
+	unsigned long mem_end;
+	unsigned short base_addr; 
+	unsigned char irq;
+	unsigned char dma;
+	unsigned char port;
+	/* 3 bytes spare */
+};
+#endif /* __UAPI_DEF_IF_IFMAP */
+
+struct if_settings {
+	unsigned int type;	/* Type of physical device or protocol */
+	unsigned int size;	/* Size of the data allocated by the caller */
+	union {
+		/* {atm/eth/dsl}_settings anyone ? */
+		raw_hdlc_proto		*raw_hdlc;
+		cisco_proto		*cisco;
+		fr_proto		*fr;
+		fr_proto_pvc		*fr_pvc;
+		fr_proto_pvc_info	*fr_pvc_info;
+		x25_hdlc_proto		*x25;
+
+		/* interface settings */
+		sync_serial_settings	*sync;
+		te1_settings		*te1;
+	} ifs_ifsu;
+};
+
+/*
+ * Interface request structure used for socket
+ * ioctl's.  All interface ioctl's must have parameter
+ * definitions which begin with ifr_name.  The
+ * remainder may be interface specific.
+ */
+
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_IFREQ
+struct ifreq {
+#define IFHWADDRLEN	6
+	union
+	{
+		char	ifrn_name[IFNAMSIZ];		/* if name, e.g. "en0" */
+	} ifr_ifrn;
+	
+	union {
+		struct	sockaddr ifru_addr;
+		struct	sockaddr ifru_dstaddr;
+		struct	sockaddr ifru_broadaddr;
+		struct	sockaddr ifru_netmask;
+		struct  sockaddr ifru_hwaddr;
+		short	ifru_flags;
+		int	ifru_ivalue;
+		int	ifru_mtu;
+		struct  ifmap ifru_map;
+		char	ifru_slave[IFNAMSIZ];	/* Just fits the size */
+		char	ifru_newname[IFNAMSIZ];
+		void *	ifru_data;
+		struct	if_settings ifru_settings;
+	} ifr_ifru;
+};
+#endif /* __UAPI_DEF_IF_IFREQ */
+
+#define ifr_name	ifr_ifrn.ifrn_name	/* interface name 	*/
+#define ifr_hwaddr	ifr_ifru.ifru_hwaddr	/* MAC address 		*/
+#define	ifr_addr	ifr_ifru.ifru_addr	/* address		*/
+#define	ifr_dstaddr	ifr_ifru.ifru_dstaddr	/* other end of p-p lnk	*/
+#define	ifr_broadaddr	ifr_ifru.ifru_broadaddr	/* broadcast address	*/
+#define	ifr_netmask	ifr_ifru.ifru_netmask	/* interface net mask	*/
+#define	ifr_flags	ifr_ifru.ifru_flags	/* flags		*/
+#define	ifr_metric	ifr_ifru.ifru_ivalue	/* metric		*/
+#define	ifr_mtu		ifr_ifru.ifru_mtu	/* mtu			*/
+#define ifr_map		ifr_ifru.ifru_map	/* device map		*/
+#define ifr_slave	ifr_ifru.ifru_slave	/* slave device		*/
+#define	ifr_data	ifr_ifru.ifru_data	/* for use by interface	*/
+#define ifr_ifindex	ifr_ifru.ifru_ivalue	/* interface index	*/
+#define ifr_bandwidth	ifr_ifru.ifru_ivalue    /* link bandwidth	*/
+#define ifr_qlen	ifr_ifru.ifru_ivalue	/* Queue length 	*/
+#define ifr_newname	ifr_ifru.ifru_newname	/* New name		*/
+#define ifr_settings	ifr_ifru.ifru_settings	/* Device/proto settings*/
+
+/*
+ * Structure used in SIOCGIFCONF request.
+ * Used to retrieve interface configuration
+ * for machine (useful for programs which
+ * must know all networks accessible).
+ */
+
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_IFCONF
+struct ifconf  {
+	int	ifc_len;			/* size of buffer	*/
+	union {
+		char *ifcu_buf;
+		struct ifreq *ifcu_req;
+	} ifc_ifcu;
+};
+#endif /* __UAPI_DEF_IF_IFCONF */
+
+#define	ifc_buf	ifc_ifcu.ifcu_buf		/* buffer address	*/
+#define	ifc_req	ifc_ifcu.ifcu_req		/* array of structures	*/
+
+#endif /* _LINUX_IF_H */
diff --git a/uapi/linux/if_addr.h b/uapi/linux/if_addr.h
new file mode 100644
index 0000000..d6db3ff
--- /dev/null
+++ b/uapi/linux/if_addr.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_IF_ADDR_H
+#define __LINUX_IF_ADDR_H
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+
+struct ifaddrmsg {
+	__u8		ifa_family;
+	__u8		ifa_prefixlen;	/* The prefix length		*/
+	__u8		ifa_flags;	/* Flags			*/
+	__u8		ifa_scope;	/* Address scope		*/
+	__u32		ifa_index;	/* Link index			*/
+};
+
+/*
+ * Important comment:
+ * IFA_ADDRESS is prefix address, rather than local interface address.
+ * It makes no difference for normally configured broadcast interfaces,
+ * but for point-to-point IFA_ADDRESS is DESTINATION address,
+ * local address is supplied in IFA_LOCAL attribute.
+ *
+ * IFA_FLAGS is a u32 attribute that extends the u8 field ifa_flags.
+ * If present, the value from struct ifaddrmsg will be ignored.
+ */
+enum {
+	IFA_UNSPEC,
+	IFA_ADDRESS,
+	IFA_LOCAL,
+	IFA_LABEL,
+	IFA_BROADCAST,
+	IFA_ANYCAST,
+	IFA_CACHEINFO,
+	IFA_MULTICAST,
+	IFA_FLAGS,
+	IFA_RT_PRIORITY,	/* u32, priority/metric for prefix route */
+	IFA_TARGET_NETNSID,
+	IFA_PROTO,		/* u8, address protocol */
+	__IFA_MAX,
+};
+
+#define IFA_MAX (__IFA_MAX - 1)
+
+/* ifa_flags */
+#define IFA_F_SECONDARY		0x01
+#define IFA_F_TEMPORARY		IFA_F_SECONDARY
+
+#define	IFA_F_NODAD		0x02
+#define IFA_F_OPTIMISTIC	0x04
+#define IFA_F_DADFAILED		0x08
+#define	IFA_F_HOMEADDRESS	0x10
+#define IFA_F_DEPRECATED	0x20
+#define IFA_F_TENTATIVE		0x40
+#define IFA_F_PERMANENT		0x80
+#define IFA_F_MANAGETEMPADDR	0x100
+#define IFA_F_NOPREFIXROUTE	0x200
+#define IFA_F_MCAUTOJOIN	0x400
+#define IFA_F_STABLE_PRIVACY	0x800
+
+struct ifa_cacheinfo {
+	__u32	ifa_prefered;
+	__u32	ifa_valid;
+	__u32	cstamp; /* created timestamp, hundredths of seconds */
+	__u32	tstamp; /* updated timestamp, hundredths of seconds */
+};
+
+/* backwards compatibility for userspace */
+#define IFA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
+#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
+
+/* ifa_proto */
+#define IFAPROT_UNSPEC		0
+#define IFAPROT_KERNEL_LO	1	/* loopback */
+#define IFAPROT_KERNEL_RA	2	/* set by kernel from router announcement */
+#define IFAPROT_KERNEL_LL	3	/* link-local set by kernel */
+
+#endif
diff --git a/uapi/linux/if_ether.h b/uapi/linux/if_ether.h
new file mode 100644
index 0000000..a1aff8e
--- /dev/null
+++ b/uapi/linux/if_ether.h
@@ -0,0 +1,181 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		Global definitions for the Ethernet IEEE 802.3 interface.
+ *
+ * Version:	@(#)if_ether.h	1.0.1a	02/08/94
+ *
+ * Author:	Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *		Donald Becker, <becker@super.org>
+ *		Alan Cox, <alan@lxorguk.ukuu.org.uk>
+ *		Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_IF_ETHER_H
+#define _LINUX_IF_ETHER_H
+
+#include <linux/types.h>
+
+/*
+ *	IEEE 802.3 Ethernet magic constants.  The frame sizes omit the preamble
+ *	and FCS/CRC (frame check sequence).
+ */
+
+#define ETH_ALEN	6		/* Octets in one ethernet addr	 */
+#define ETH_TLEN	2		/* Octets in ethernet type field */
+#define ETH_HLEN	14		/* Total octets in header.	 */
+#define ETH_ZLEN	60		/* Min. octets in frame sans FCS */
+#define ETH_DATA_LEN	1500		/* Max. octets in payload	 */
+#define ETH_FRAME_LEN	1514		/* Max. octets in frame sans FCS */
+#define ETH_FCS_LEN	4		/* Octets in the FCS		 */
+
+#define ETH_MIN_MTU	68		/* Min IPv4 MTU per RFC791	*/
+#define ETH_MAX_MTU	0xFFFFU		/* 65535, same as IP_MAX_MTU	*/
+
+/*
+ *	These are the defined Ethernet Protocol ID's.
+ */
+
+#define ETH_P_LOOP	0x0060		/* Ethernet Loopback packet	*/
+#define ETH_P_PUP	0x0200		/* Xerox PUP packet		*/
+#define ETH_P_PUPAT	0x0201		/* Xerox PUP Addr Trans packet	*/
+#define ETH_P_TSN	0x22F0		/* TSN (IEEE 1722) packet	*/
+#define ETH_P_ERSPAN2	0x22EB		/* ERSPAN version 2 (type III)	*/
+#define ETH_P_IP	0x0800		/* Internet Protocol packet	*/
+#define ETH_P_X25	0x0805		/* CCITT X.25			*/
+#define ETH_P_ARP	0x0806		/* Address Resolution packet	*/
+#define	ETH_P_BPQ	0x08FF		/* G8BPQ AX.25 Ethernet Packet	[ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_IEEEPUP	0x0a00		/* Xerox IEEE802.3 PUP packet */
+#define ETH_P_IEEEPUPAT	0x0a01		/* Xerox IEEE802.3 PUP Addr Trans packet */
+#define ETH_P_BATMAN	0x4305		/* B.A.T.M.A.N.-Advanced packet [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_DEC       0x6000          /* DEC Assigned proto           */
+#define ETH_P_DNA_DL    0x6001          /* DEC DNA Dump/Load            */
+#define ETH_P_DNA_RC    0x6002          /* DEC DNA Remote Console       */
+#define ETH_P_DNA_RT    0x6003          /* DEC DNA Routing              */
+#define ETH_P_LAT       0x6004          /* DEC LAT                      */
+#define ETH_P_DIAG      0x6005          /* DEC Diagnostics              */
+#define ETH_P_CUST      0x6006          /* DEC Customer use             */
+#define ETH_P_SCA       0x6007          /* DEC Systems Comms Arch       */
+#define ETH_P_TEB	0x6558		/* Trans Ether Bridging		*/
+#define ETH_P_RARP      0x8035		/* Reverse Addr Res packet	*/
+#define ETH_P_ATALK	0x809B		/* Appletalk DDP		*/
+#define ETH_P_AARP	0x80F3		/* Appletalk AARP		*/
+#define ETH_P_8021Q	0x8100          /* 802.1Q VLAN Extended Header  */
+#define ETH_P_ERSPAN	0x88BE		/* ERSPAN type II		*/
+#define ETH_P_IPX	0x8137		/* IPX over DIX			*/
+#define ETH_P_IPV6	0x86DD		/* IPv6 over bluebook		*/
+#define ETH_P_PAUSE	0x8808		/* IEEE Pause frames. See 802.3 31B */
+#define ETH_P_SLOW	0x8809		/* Slow Protocol. See 802.3ad 43B */
+#define ETH_P_WCCP	0x883E		/* Web-cache coordination protocol
+					 * defined in draft-wilson-wrec-wccp-v2-00.txt */
+#define ETH_P_MPLS_UC	0x8847		/* MPLS Unicast traffic		*/
+#define ETH_P_MPLS_MC	0x8848		/* MPLS Multicast traffic	*/
+#define ETH_P_ATMMPOA	0x884c		/* MultiProtocol Over ATM	*/
+#define ETH_P_PPP_DISC	0x8863		/* PPPoE discovery messages     */
+#define ETH_P_PPP_SES	0x8864		/* PPPoE session messages	*/
+#define ETH_P_LINK_CTL	0x886c		/* HPNA, wlan link local tunnel */
+#define ETH_P_ATMFATE	0x8884		/* Frame-based ATM Transport
+					 * over Ethernet
+					 */
+#define ETH_P_PAE	0x888E		/* Port Access Entity (IEEE 802.1X) */
+#define ETH_P_PROFINET	0x8892		/* PROFINET			*/
+#define ETH_P_REALTEK	0x8899          /* Multiple proprietary protocols */
+#define ETH_P_AOE	0x88A2		/* ATA over Ethernet		*/
+#define ETH_P_ETHERCAT	0x88A4		/* EtherCAT			*/
+#define ETH_P_8021AD	0x88A8          /* 802.1ad Service VLAN		*/
+#define ETH_P_802_EX1	0x88B5		/* 802.1 Local Experimental 1.  */
+#define ETH_P_PREAUTH	0x88C7		/* 802.11 Preauthentication */
+#define ETH_P_TIPC	0x88CA		/* TIPC 			*/
+#define ETH_P_LLDP	0x88CC		/* Link Layer Discovery Protocol */
+#define ETH_P_MRP	0x88E3		/* Media Redundancy Protocol	*/
+#define ETH_P_MACSEC	0x88E5		/* 802.1ae MACsec */
+#define ETH_P_8021AH	0x88E7          /* 802.1ah Backbone Service Tag */
+#define ETH_P_MVRP	0x88F5          /* 802.1Q MVRP                  */
+#define ETH_P_1588	0x88F7		/* IEEE 1588 Timesync */
+#define ETH_P_NCSI	0x88F8		/* NCSI protocol		*/
+#define ETH_P_PRP	0x88FB		/* IEC 62439-3 PRP/HSRv0	*/
+#define ETH_P_CFM	0x8902		/* Connectivity Fault Management */
+#define ETH_P_FCOE	0x8906		/* Fibre Channel over Ethernet  */
+#define ETH_P_IBOE	0x8915		/* Infiniband over Ethernet	*/
+#define ETH_P_TDLS	0x890D          /* TDLS */
+#define ETH_P_FIP	0x8914		/* FCoE Initialization Protocol */
+#define ETH_P_80221	0x8917		/* IEEE 802.21 Media Independent Handover Protocol */
+#define ETH_P_HSR	0x892F		/* IEC 62439-3 HSRv1	*/
+#define ETH_P_NSH	0x894F		/* Network Service Header */
+#define ETH_P_LOOPBACK	0x9000		/* Ethernet loopback packet, per IEEE 802.3 */
+#define ETH_P_QINQ1	0x9100		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_QINQ2	0x9200		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_QINQ3	0x9300		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_EDSA	0xDADA		/* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_DSA_8021Q	0xDADB		/* Fake VLAN Header for DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_DSA_A5PSW	0xE001		/* A5PSW Tag Value [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_IFE	0xED3E		/* ForCES inter-FE LFB type */
+#define ETH_P_AF_IUCV   0xFBFB		/* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */
+
+#define ETH_P_802_3_MIN	0x0600		/* If the value in the ethernet type is more than this value
+					 * then the frame is Ethernet II. Else it is 802.3 */
+
+/*
+ *	Non DIX types. Won't clash for 1500 types.
+ */
+
+#define ETH_P_802_3	0x0001		/* Dummy type for 802.3 frames  */
+#define ETH_P_AX25	0x0002		/* Dummy protocol id for AX.25  */
+#define ETH_P_ALL	0x0003		/* Every packet (be careful!!!) */
+#define ETH_P_802_2	0x0004		/* 802.2 frames 		*/
+#define ETH_P_SNAP	0x0005		/* Internal only		*/
+#define ETH_P_DDCMP     0x0006          /* DEC DDCMP: Internal only     */
+#define ETH_P_WAN_PPP   0x0007          /* Dummy type for WAN PPP frames*/
+#define ETH_P_PPP_MP    0x0008          /* Dummy type for PPP MP frames */
+#define ETH_P_LOCALTALK 0x0009		/* Localtalk pseudo type 	*/
+#define ETH_P_CAN	0x000C		/* CAN: Controller Area Network */
+#define ETH_P_CANFD	0x000D		/* CANFD: CAN flexible data rate*/
+#define ETH_P_CANXL	0x000E		/* CANXL: eXtended frame Length */
+#define ETH_P_PPPTALK	0x0010		/* Dummy type for Atalk over PPP*/
+#define ETH_P_TR_802_2	0x0011		/* 802.2 frames 		*/
+#define ETH_P_MOBITEX	0x0015		/* Mobitex (kaz@cafe.net)	*/
+#define ETH_P_CONTROL	0x0016		/* Card specific control frames */
+#define ETH_P_IRDA	0x0017		/* Linux-IrDA			*/
+#define ETH_P_ECONET	0x0018		/* Acorn Econet			*/
+#define ETH_P_HDLC	0x0019		/* HDLC frames			*/
+#define ETH_P_ARCNET	0x001A		/* 1A for ArcNet :-)            */
+#define ETH_P_DSA	0x001B		/* Distributed Switch Arch.	*/
+#define ETH_P_TRAILER	0x001C		/* Trailer switch tagging	*/
+#define ETH_P_PHONET	0x00F5		/* Nokia Phonet frames          */
+#define ETH_P_IEEE802154 0x00F6		/* IEEE802.15.4 frame		*/
+#define ETH_P_CAIF	0x00F7		/* ST-Ericsson CAIF protocol	*/
+#define ETH_P_XDSA	0x00F8		/* Multiplexed DSA protocol	*/
+#define ETH_P_MAP	0x00F9		/* Qualcomm multiplexing and
+					 * aggregation protocol
+					 */
+#define ETH_P_MCTP	0x00FA		/* Management component transport
+					 * protocol packets
+					 */
+
+/*
+ *	This is an Ethernet frame header.
+ */
+
+/* allow libcs like musl to deactivate this, glibc does not implement this. */
+#ifndef __UAPI_DEF_ETHHDR
+#define __UAPI_DEF_ETHHDR		1
+#endif
+
+#if __UAPI_DEF_ETHHDR
+struct ethhdr {
+	unsigned char	h_dest[ETH_ALEN];	/* destination eth addr	*/
+	unsigned char	h_source[ETH_ALEN];	/* source ether addr	*/
+	__be16		h_proto;		/* packet type ID field	*/
+} __attribute__((packed));
+#endif
+
+
+#endif /* _LINUX_IF_ETHER_H */
diff --git a/uapi/linux/if_link.h b/uapi/linux/if_link.h
index 153fcb9..02af33c 100644
--- a/uapi/linux/if_link.h
+++ b/uapi/linux/if_link.h
@@ -372,6 +372,11 @@
 	IFLA_TSO_MAX_SEGS,
 	IFLA_ALLMULTI,		/* Allmulti count: > 0 means acts ALLMULTI */
 
+	IFLA_DEVLINK_PORT,
+
+	IFLA_GSO_IPV4_MAX_SIZE,
+	IFLA_GRO_IPV4_MAX_SIZE,
+
 	__IFLA_MAX
 };
 
@@ -559,6 +564,10 @@
 	IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT,
 	IFLA_BRPORT_MCAST_EHT_HOSTS_CNT,
 	IFLA_BRPORT_LOCKED,
+	IFLA_BRPORT_MAB,
+	IFLA_BRPORT_MCAST_N_GROUPS,
+	IFLA_BRPORT_MCAST_MAX_GROUPS,
+	IFLA_BRPORT_NEIGH_VLAN_SUPPRESS,
 	__IFLA_BRPORT_MAX
 };
 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
@@ -625,6 +634,7 @@
 	IFLA_MACVLAN_MACADDR_COUNT,
 	IFLA_MACVLAN_BC_QUEUE_LEN,
 	IFLA_MACVLAN_BC_QUEUE_LEN_USED,
+	IFLA_MACVLAN_BC_CUTOFF,
 	__IFLA_MACVLAN_MAX,
 };
 
@@ -816,6 +826,7 @@
 	IFLA_VXLAN_TTL_INHERIT,
 	IFLA_VXLAN_DF,
 	IFLA_VXLAN_VNIFILTER, /* only applicable with COLLECT_METADATA mode */
+	IFLA_VXLAN_LOCALBYPASS,
 	__IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX	(__IFLA_VXLAN_MAX - 1)
diff --git a/uapi/linux/libc-compat.h b/uapi/linux/libc-compat.h
new file mode 100644
index 0000000..a159991
--- /dev/null
+++ b/uapi/linux/libc-compat.h
@@ -0,0 +1,267 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Compatibility interface for userspace libc header coordination:
+ *
+ * Define compatibility macros that are used to control the inclusion or
+ * exclusion of UAPI structures and definitions in coordination with another
+ * userspace C library.
+ *
+ * This header is intended to solve the problem of UAPI definitions that
+ * conflict with userspace definitions. If a UAPI header has such conflicting
+ * definitions then the solution is as follows:
+ *
+ * * Synchronize the UAPI header and the libc headers so either one can be
+ *   used and such that the ABI is preserved. If this is not possible then
+ *   no simple compatibility interface exists (you need to write translating
+ *   wrappers and rename things) and you can't use this interface.
+ *
+ * Then follow this process:
+ *
+ * (a) Include libc-compat.h in the UAPI header.
+ *      e.g. #include <linux/libc-compat.h>
+ *     This include must be as early as possible.
+ *
+ * (b) In libc-compat.h add enough code to detect that the comflicting
+ *     userspace libc header has been included first.
+ *
+ * (c) If the userspace libc header has been included first define a set of
+ *     guard macros of the form __UAPI_DEF_FOO and set their values to 1, else
+ *     set their values to 0.
+ *
+ * (d) Back in the UAPI header with the conflicting definitions, guard the
+ *     definitions with:
+ *     #if __UAPI_DEF_FOO
+ *       ...
+ *     #endif
+ *
+ * This fixes the situation where the linux headers are included *after* the
+ * libc headers. To fix the problem with the inclusion in the other order the
+ * userspace libc headers must be fixed like this:
+ *
+ * * For all definitions that conflict with kernel definitions wrap those
+ *   defines in the following:
+ *   #if !__UAPI_DEF_FOO
+ *     ...
+ *   #endif
+ *
+ * This prevents the redefinition of a construct already defined by the kernel.
+ */
+#ifndef _LIBC_COMPAT_H
+#define _LIBC_COMPAT_H
+
+/* We have included glibc headers... */
+#if defined(__GLIBC__)
+
+/* Coordinate with glibc net/if.h header. */
+#if defined(_NET_IF_H) && defined(__USE_MISC)
+
+/* GLIBC headers included first so don't define anything
+ * that would already be defined. */
+
+#define __UAPI_DEF_IF_IFCONF 0
+#define __UAPI_DEF_IF_IFMAP 0
+#define __UAPI_DEF_IF_IFNAMSIZ 0
+#define __UAPI_DEF_IF_IFREQ 0
+/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0
+/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
+#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
+
+#else /* _NET_IF_H */
+
+/* Linux headers included first, and we must define everything
+ * we need. The expectation is that glibc will check the
+ * __UAPI_DEF_* defines and adjust appropriately. */
+
+#define __UAPI_DEF_IF_IFCONF 1
+#define __UAPI_DEF_IF_IFMAP 1
+#define __UAPI_DEF_IF_IFNAMSIZ 1
+#define __UAPI_DEF_IF_IFREQ 1
+/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1
+/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
+
+#endif /* _NET_IF_H */
+
+/* Coordinate with glibc netinet/in.h header. */
+#if defined(_NETINET_IN_H)
+
+/* GLIBC headers included first so don't define anything
+ * that would already be defined. */
+#define __UAPI_DEF_IN_ADDR		0
+#define __UAPI_DEF_IN_IPPROTO		0
+#define __UAPI_DEF_IN_PKTINFO		0
+#define __UAPI_DEF_IP_MREQ		0
+#define __UAPI_DEF_SOCKADDR_IN		0
+#define __UAPI_DEF_IN_CLASS		0
+
+#define __UAPI_DEF_IN6_ADDR		0
+/* The exception is the in6_addr macros which must be defined
+ * if the glibc code didn't define them. This guard matches
+ * the guard in glibc/inet/netinet/in.h which defines the
+ * additional in6_addr macros e.g. s6_addr16, and s6_addr32. */
+#if defined(__USE_MISC) || defined (__USE_GNU)
+#define __UAPI_DEF_IN6_ADDR_ALT		0
+#else
+#define __UAPI_DEF_IN6_ADDR_ALT		1
+#endif
+#define __UAPI_DEF_SOCKADDR_IN6		0
+#define __UAPI_DEF_IPV6_MREQ		0
+#define __UAPI_DEF_IPPROTO_V6		0
+#define __UAPI_DEF_IPV6_OPTIONS		0
+#define __UAPI_DEF_IN6_PKTINFO		0
+#define __UAPI_DEF_IP6_MTUINFO		0
+
+#else
+
+/* Linux headers included first, and we must define everything
+ * we need. The expectation is that glibc will check the
+ * __UAPI_DEF_* defines and adjust appropriately. */
+#define __UAPI_DEF_IN_ADDR		1
+#define __UAPI_DEF_IN_IPPROTO		1
+#define __UAPI_DEF_IN_PKTINFO		1
+#define __UAPI_DEF_IP_MREQ		1
+#define __UAPI_DEF_SOCKADDR_IN		1
+#define __UAPI_DEF_IN_CLASS		1
+
+#define __UAPI_DEF_IN6_ADDR		1
+/* We unconditionally define the in6_addr macros and glibc must
+ * coordinate. */
+#define __UAPI_DEF_IN6_ADDR_ALT		1
+#define __UAPI_DEF_SOCKADDR_IN6		1
+#define __UAPI_DEF_IPV6_MREQ		1
+#define __UAPI_DEF_IPPROTO_V6		1
+#define __UAPI_DEF_IPV6_OPTIONS		1
+#define __UAPI_DEF_IN6_PKTINFO		1
+#define __UAPI_DEF_IP6_MTUINFO		1
+
+#endif /* _NETINET_IN_H */
+
+/* Coordinate with glibc netipx/ipx.h header. */
+#if defined(__NETIPX_IPX_H)
+
+#define __UAPI_DEF_SOCKADDR_IPX			0
+#define __UAPI_DEF_IPX_ROUTE_DEFINITION		0
+#define __UAPI_DEF_IPX_INTERFACE_DEFINITION	0
+#define __UAPI_DEF_IPX_CONFIG_DATA		0
+#define __UAPI_DEF_IPX_ROUTE_DEF		0
+
+#else /* defined(__NETIPX_IPX_H) */
+
+#define __UAPI_DEF_SOCKADDR_IPX			1
+#define __UAPI_DEF_IPX_ROUTE_DEFINITION		1
+#define __UAPI_DEF_IPX_INTERFACE_DEFINITION	1
+#define __UAPI_DEF_IPX_CONFIG_DATA		1
+#define __UAPI_DEF_IPX_ROUTE_DEF		1
+
+#endif /* defined(__NETIPX_IPX_H) */
+
+/* Definitions for xattr.h */
+#if defined(_SYS_XATTR_H)
+#define __UAPI_DEF_XATTR		0
+#else
+#define __UAPI_DEF_XATTR		1
+#endif
+
+/* If we did not see any headers from any supported C libraries,
+ * or we are being included in the kernel, then define everything
+ * that we need. Check for previous __UAPI_* definitions to give
+ * unsupported C libraries a way to opt out of any kernel definition. */
+#else /* !defined(__GLIBC__) */
+
+/* Definitions for if.h */
+#ifndef __UAPI_DEF_IF_IFCONF
+#define __UAPI_DEF_IF_IFCONF 1
+#endif
+#ifndef __UAPI_DEF_IF_IFMAP
+#define __UAPI_DEF_IF_IFMAP 1
+#endif
+#ifndef __UAPI_DEF_IF_IFNAMSIZ
+#define __UAPI_DEF_IF_IFNAMSIZ 1
+#endif
+#ifndef __UAPI_DEF_IF_IFREQ
+#define __UAPI_DEF_IF_IFREQ 1
+#endif
+/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
+#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1
+#endif
+/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
+#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
+#endif
+
+/* Definitions for in.h */
+#ifndef __UAPI_DEF_IN_ADDR
+#define __UAPI_DEF_IN_ADDR		1
+#endif
+#ifndef __UAPI_DEF_IN_IPPROTO
+#define __UAPI_DEF_IN_IPPROTO		1
+#endif
+#ifndef __UAPI_DEF_IN_PKTINFO
+#define __UAPI_DEF_IN_PKTINFO		1
+#endif
+#ifndef __UAPI_DEF_IP_MREQ
+#define __UAPI_DEF_IP_MREQ		1
+#endif
+#ifndef __UAPI_DEF_SOCKADDR_IN
+#define __UAPI_DEF_SOCKADDR_IN		1
+#endif
+#ifndef __UAPI_DEF_IN_CLASS
+#define __UAPI_DEF_IN_CLASS		1
+#endif
+
+/* Definitions for in6.h */
+#ifndef __UAPI_DEF_IN6_ADDR
+#define __UAPI_DEF_IN6_ADDR		1
+#endif
+#ifndef __UAPI_DEF_IN6_ADDR_ALT
+#define __UAPI_DEF_IN6_ADDR_ALT		1
+#endif
+#ifndef __UAPI_DEF_SOCKADDR_IN6
+#define __UAPI_DEF_SOCKADDR_IN6		1
+#endif
+#ifndef __UAPI_DEF_IPV6_MREQ
+#define __UAPI_DEF_IPV6_MREQ		1
+#endif
+#ifndef __UAPI_DEF_IPPROTO_V6
+#define __UAPI_DEF_IPPROTO_V6		1
+#endif
+#ifndef __UAPI_DEF_IPV6_OPTIONS
+#define __UAPI_DEF_IPV6_OPTIONS		1
+#endif
+#ifndef __UAPI_DEF_IN6_PKTINFO
+#define __UAPI_DEF_IN6_PKTINFO		1
+#endif
+#ifndef __UAPI_DEF_IP6_MTUINFO
+#define __UAPI_DEF_IP6_MTUINFO		1
+#endif
+
+/* Definitions for ipx.h */
+#ifndef __UAPI_DEF_SOCKADDR_IPX
+#define __UAPI_DEF_SOCKADDR_IPX			1
+#endif
+#ifndef __UAPI_DEF_IPX_ROUTE_DEFINITION
+#define __UAPI_DEF_IPX_ROUTE_DEFINITION		1
+#endif
+#ifndef __UAPI_DEF_IPX_INTERFACE_DEFINITION
+#define __UAPI_DEF_IPX_INTERFACE_DEFINITION	1
+#endif
+#ifndef __UAPI_DEF_IPX_CONFIG_DATA
+#define __UAPI_DEF_IPX_CONFIG_DATA		1
+#endif
+#ifndef __UAPI_DEF_IPX_ROUTE_DEF
+#define __UAPI_DEF_IPX_ROUTE_DEF		1
+#endif
+
+/* Definitions for xattr.h */
+#ifndef __UAPI_DEF_XATTR
+#define __UAPI_DEF_XATTR		1
+#endif
+
+#endif /* __GLIBC__ */
+
+#endif /* _LIBC_COMPAT_H */
diff --git a/uapi/linux/neighbour.h b/uapi/linux/neighbour.h
new file mode 100644
index 0000000..5e67a7e
--- /dev/null
+++ b/uapi/linux/neighbour.h
@@ -0,0 +1,224 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_NEIGHBOUR_H
+#define __LINUX_NEIGHBOUR_H
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+
+struct ndmsg {
+	__u8		ndm_family;
+	__u8		ndm_pad1;
+	__u16		ndm_pad2;
+	__s32		ndm_ifindex;
+	__u16		ndm_state;
+	__u8		ndm_flags;
+	__u8		ndm_type;
+};
+
+enum {
+	NDA_UNSPEC,
+	NDA_DST,
+	NDA_LLADDR,
+	NDA_CACHEINFO,
+	NDA_PROBES,
+	NDA_VLAN,
+	NDA_PORT,
+	NDA_VNI,
+	NDA_IFINDEX,
+	NDA_MASTER,
+	NDA_LINK_NETNSID,
+	NDA_SRC_VNI,
+	NDA_PROTOCOL,  /* Originator of entry */
+	NDA_NH_ID,
+	NDA_FDB_EXT_ATTRS,
+	NDA_FLAGS_EXT,
+	NDA_NDM_STATE_MASK,
+	NDA_NDM_FLAGS_MASK,
+	__NDA_MAX
+};
+
+#define NDA_MAX (__NDA_MAX - 1)
+
+/*
+ *	Neighbor Cache Entry Flags
+ */
+
+#define NTF_USE		(1 << 0)
+#define NTF_SELF	(1 << 1)
+#define NTF_MASTER	(1 << 2)
+#define NTF_PROXY	(1 << 3)	/* == ATF_PUBL */
+#define NTF_EXT_LEARNED	(1 << 4)
+#define NTF_OFFLOADED   (1 << 5)
+#define NTF_STICKY	(1 << 6)
+#define NTF_ROUTER	(1 << 7)
+/* Extended flags under NDA_FLAGS_EXT: */
+#define NTF_EXT_MANAGED		(1 << 0)
+#define NTF_EXT_LOCKED		(1 << 1)
+
+/*
+ *	Neighbor Cache Entry States.
+ */
+
+#define NUD_INCOMPLETE	0x01
+#define NUD_REACHABLE	0x02
+#define NUD_STALE	0x04
+#define NUD_DELAY	0x08
+#define NUD_PROBE	0x10
+#define NUD_FAILED	0x20
+
+/* Dummy states */
+#define NUD_NOARP	0x40
+#define NUD_PERMANENT	0x80
+#define NUD_NONE	0x00
+
+/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change and make no
+ * address resolution or NUD.
+ *
+ * NUD_PERMANENT also cannot be deleted by garbage collectors. This holds true
+ * for dynamic entries with NTF_EXT_LEARNED flag as well. However, upon carrier
+ * down event, NUD_PERMANENT entries are not flushed whereas NTF_EXT_LEARNED
+ * flagged entries explicitly are (which is also consistent with the routing
+ * subsystem).
+ *
+ * When NTF_EXT_LEARNED is set for a bridge fdb entry the different cache entry
+ * states don't make sense and thus are ignored. Such entries don't age and
+ * can roam.
+ *
+ * NTF_EXT_MANAGED flagged neigbor entries are managed by the kernel on behalf
+ * of a user space control plane, and automatically refreshed so that (if
+ * possible) they remain in NUD_REACHABLE state.
+ *
+ * NTF_EXT_LOCKED flagged bridge FDB entries are entries generated by the
+ * bridge in response to a host trying to communicate via a locked bridge port
+ * with MAB enabled. Their purpose is to notify user space that a host requires
+ * authentication.
+ */
+
+struct nda_cacheinfo {
+	__u32		ndm_confirmed;
+	__u32		ndm_used;
+	__u32		ndm_updated;
+	__u32		ndm_refcnt;
+};
+
+/*****************************************************************
+ *		Neighbour tables specific messages.
+ *
+ * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the
+ * NLM_F_DUMP flag set. Every neighbour table configuration is
+ * spread over multiple messages to avoid running into message
+ * size limits on systems with many interfaces. The first message
+ * in the sequence transports all not device specific data such as
+ * statistics, configuration, and the default parameter set.
+ * This message is followed by 0..n messages carrying device
+ * specific parameter sets.
+ * Although the ordering should be sufficient, NDTA_NAME can be
+ * used to identify sequences. The initial message can be identified
+ * by checking for NDTA_CONFIG. The device specific messages do
+ * not contain this TLV but have NDTPA_IFINDEX set to the
+ * corresponding interface index.
+ *
+ * To change neighbour table attributes, send RTM_SETNEIGHTBL
+ * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3],
+ * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked
+ * otherwise. Device specific parameter sets can be changed by
+ * setting NDTPA_IFINDEX to the interface index of the corresponding
+ * device.
+ ****/
+
+struct ndt_stats {
+	__u64		ndts_allocs;
+	__u64		ndts_destroys;
+	__u64		ndts_hash_grows;
+	__u64		ndts_res_failed;
+	__u64		ndts_lookups;
+	__u64		ndts_hits;
+	__u64		ndts_rcv_probes_mcast;
+	__u64		ndts_rcv_probes_ucast;
+	__u64		ndts_periodic_gc_runs;
+	__u64		ndts_forced_gc_runs;
+	__u64		ndts_table_fulls;
+};
+
+enum {
+	NDTPA_UNSPEC,
+	NDTPA_IFINDEX,			/* u32, unchangeable */
+	NDTPA_REFCNT,			/* u32, read-only */
+	NDTPA_REACHABLE_TIME,		/* u64, read-only, msecs */
+	NDTPA_BASE_REACHABLE_TIME,	/* u64, msecs */
+	NDTPA_RETRANS_TIME,		/* u64, msecs */
+	NDTPA_GC_STALETIME,		/* u64, msecs */
+	NDTPA_DELAY_PROBE_TIME,		/* u64, msecs */
+	NDTPA_QUEUE_LEN,		/* u32 */
+	NDTPA_APP_PROBES,		/* u32 */
+	NDTPA_UCAST_PROBES,		/* u32 */
+	NDTPA_MCAST_PROBES,		/* u32 */
+	NDTPA_ANYCAST_DELAY,		/* u64, msecs */
+	NDTPA_PROXY_DELAY,		/* u64, msecs */
+	NDTPA_PROXY_QLEN,		/* u32 */
+	NDTPA_LOCKTIME,			/* u64, msecs */
+	NDTPA_QUEUE_LENBYTES,		/* u32 */
+	NDTPA_MCAST_REPROBES,		/* u32 */
+	NDTPA_PAD,
+	NDTPA_INTERVAL_PROBE_TIME_MS,	/* u64, msecs */
+	__NDTPA_MAX
+};
+#define NDTPA_MAX (__NDTPA_MAX - 1)
+
+struct ndtmsg {
+	__u8		ndtm_family;
+	__u8		ndtm_pad1;
+	__u16		ndtm_pad2;
+};
+
+struct ndt_config {
+	__u16		ndtc_key_len;
+	__u16		ndtc_entry_size;
+	__u32		ndtc_entries;
+	__u32		ndtc_last_flush;	/* delta to now in msecs */
+	__u32		ndtc_last_rand;		/* delta to now in msecs */
+	__u32		ndtc_hash_rnd;
+	__u32		ndtc_hash_mask;
+	__u32		ndtc_hash_chain_gc;
+	__u32		ndtc_proxy_qlen;
+};
+
+enum {
+	NDTA_UNSPEC,
+	NDTA_NAME,			/* char *, unchangeable */
+	NDTA_THRESH1,			/* u32 */
+	NDTA_THRESH2,			/* u32 */
+	NDTA_THRESH3,			/* u32 */
+	NDTA_CONFIG,			/* struct ndt_config, read-only */
+	NDTA_PARMS,			/* nested TLV NDTPA_* */
+	NDTA_STATS,			/* struct ndt_stats, read-only */
+	NDTA_GC_INTERVAL,		/* u64, msecs */
+	NDTA_PAD,
+	__NDTA_MAX
+};
+#define NDTA_MAX (__NDTA_MAX - 1)
+
+ /* FDB activity notification bits used in NFEA_ACTIVITY_NOTIFY:
+  * - FDB_NOTIFY_BIT - notify on activity/expire for any entry
+  * - FDB_NOTIFY_INACTIVE_BIT - mark as inactive to avoid multiple notifications
+  */
+enum {
+	FDB_NOTIFY_BIT		= (1 << 0),
+	FDB_NOTIFY_INACTIVE_BIT	= (1 << 1)
+};
+
+/* embedded into NDA_FDB_EXT_ATTRS:
+ * [NDA_FDB_EXT_ATTRS] = {
+ *     [NFEA_ACTIVITY_NOTIFY]
+ *     ...
+ * }
+ */
+enum {
+	NFEA_UNSPEC,
+	NFEA_ACTIVITY_NOTIFY,
+	NFEA_DONT_REFRESH,
+	__NFEA_MAX
+};
+#define NFEA_MAX (__NFEA_MAX - 1)
+
+#endif
diff --git a/uapi/linux/net_tstamp.h b/uapi/linux/net_tstamp.h
index 55501e5..a2c66b3 100644
--- a/uapi/linux/net_tstamp.h
+++ b/uapi/linux/net_tstamp.h
@@ -31,8 +31,9 @@
 	SOF_TIMESTAMPING_OPT_PKTINFO = (1<<13),
 	SOF_TIMESTAMPING_OPT_TX_SWHW = (1<<14),
 	SOF_TIMESTAMPING_BIND_PHC = (1 << 15),
+	SOF_TIMESTAMPING_OPT_ID_TCP = (1 << 16),
 
-	SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_BIND_PHC,
+	SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_ID_TCP,
 	SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) |
 				 SOF_TIMESTAMPING_LAST
 };
diff --git a/uapi/linux/posix_types.h b/uapi/linux/posix_types.h
new file mode 100644
index 0000000..9a7a740
--- /dev/null
+++ b/uapi/linux/posix_types.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_POSIX_TYPES_H
+#define _LINUX_POSIX_TYPES_H
+
+#include <linux/stddef.h>
+
+/*
+ * This allows for 1024 file descriptors: if NR_OPEN is ever grown
+ * beyond that you'll have to change this too. But 1024 fd's seem to be
+ * enough even for such "real" unices like OSF/1, so hopefully this is
+ * one limit that doesn't have to be changed [again].
+ *
+ * Note that POSIX wants the FD_CLEAR(fd,fdsetp) defines to be in
+ * <sys/time.h> (and thus <linux/time.h>) - but this is a more logical
+ * place for them. Solved by having dummy defines in <sys/time.h>.
+ */
+
+/*
+ * This macro may have been defined in <gnu/types.h>. But we always
+ * use the one here.
+ */
+#undef __FD_SETSIZE
+#define __FD_SETSIZE	1024
+
+typedef struct {
+	unsigned long fds_bits[__FD_SETSIZE / (8 * sizeof(long))];
+} __kernel_fd_set;
+
+/* Type of a signal handler.  */
+typedef void (*__kernel_sighandler_t)(int);
+
+/* Type of a SYSV IPC key.  */
+typedef int __kernel_key_t;
+typedef int __kernel_mqd_t;
+
+#include <asm/posix_types.h>
+
+#endif /* _LINUX_POSIX_TYPES_H */
diff --git a/uapi/linux/rtnetlink.h b/uapi/linux/rtnetlink.h
index f4a540c..2132e94 100644
--- a/uapi/linux/rtnetlink.h
+++ b/uapi/linux/rtnetlink.h
@@ -635,6 +635,7 @@
 	TCA_INGRESS_BLOCK,
 	TCA_EGRESS_BLOCK,
 	TCA_DUMP_FLAGS,
+	TCA_EXT_WARN_MSG,
 	__TCA_MAX
 };
 
@@ -786,6 +787,7 @@
 	TCA_ROOT_FLAGS,
 	TCA_ROOT_COUNT,
 	TCA_ROOT_TIME_DELTA, /* in msecs */
+	TCA_ROOT_EXT_WARN_MSG,
 	__TCA_ROOT_MAX,
 #define	TCA_ROOT_MAX (__TCA_ROOT_MAX - 1)
 };
diff --git a/uapi/linux/socket.h b/uapi/linux/socket.h
new file mode 100644
index 0000000..89c227f
--- /dev/null
+++ b/uapi/linux/socket.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_SOCKET_H
+#define _LINUX_SOCKET_H
+
+/*
+ * Desired design of maximum size and alignment (see RFC2553)
+ */
+#define _K_SS_MAXSIZE	128	/* Implementation specific max size */
+
+typedef unsigned short __kernel_sa_family_t;
+
+/*
+ * The definition uses anonymous union and struct in order to control the
+ * default alignment.
+ */
+struct __kernel_sockaddr_storage {
+	union {
+		struct {
+			__kernel_sa_family_t	ss_family; /* address family */
+			/* Following field(s) are implementation specific */
+			char __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
+				/* space to achieve desired size, */
+				/* _SS_MAXSIZE value minus size of ss_family */
+		};
+		void *__align; /* implementation specific desired alignment */
+	};
+};
+
+#define SOCK_SNDBUF_LOCK	1
+#define SOCK_RCVBUF_LOCK	2
+
+#define SOCK_BUF_LOCK_MASK (SOCK_SNDBUF_LOCK | SOCK_RCVBUF_LOCK)
+
+#define SOCK_TXREHASH_DEFAULT	255
+#define SOCK_TXREHASH_DISABLED	0
+#define SOCK_TXREHASH_ENABLED	1
+
+#endif /* _LINUX_SOCKET_H */
diff --git a/uapi/linux/stddef.h b/uapi/linux/stddef.h
new file mode 100644
index 0000000..bb6ea51
--- /dev/null
+++ b/uapi/linux/stddef.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_STDDEF_H
+#define _LINUX_STDDEF_H
+
+
+
+#ifndef __always_inline
+#define __always_inline __inline__
+#endif
+
+/**
+ * __struct_group() - Create a mirrored named and anonyomous struct
+ *
+ * @TAG: The tag name for the named sub-struct (usually empty)
+ * @NAME: The identifier name of the mirrored sub-struct
+ * @ATTRS: Any struct attributes (usually empty)
+ * @MEMBERS: The member declarations for the mirrored structs
+ *
+ * Used to create an anonymous union of two structs with identical layout
+ * and size: one anonymous and one named. The former's members can be used
+ * normally without sub-struct naming, and the latter can be used to
+ * reason about the start, end, and size of the group of struct members.
+ * The named struct can also be explicitly tagged for layer reuse, as well
+ * as both having struct attributes appended.
+ */
+#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \
+	union { \
+		struct { MEMBERS } ATTRS; \
+		struct TAG { MEMBERS } ATTRS NAME; \
+	}
+
+/**
+ * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
+ *
+ * @TYPE: The type of each flexible array element
+ * @NAME: The name of the flexible array member
+ *
+ * In order to have a flexible array member in a union or alone in a
+ * struct, it needs to be wrapped in an anonymous struct with at least 1
+ * named member, but that member can be empty.
+ */
+#define __DECLARE_FLEX_ARRAY(TYPE, NAME)	\
+	struct { \
+		struct { } __empty_ ## NAME; \
+		TYPE NAME[]; \
+	}
+#endif
diff --git a/uapi/linux/types.h b/uapi/linux/types.h
new file mode 100644
index 0000000..e670013
--- /dev/null
+++ b/uapi/linux/types.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_TYPES_H
+#define _LINUX_TYPES_H
+
+#include <asm/types.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/posix_types.h>
+
+#ifdef __SIZEOF_INT128__
+typedef __signed__ __int128 __s128 __attribute__((aligned(16)));
+typedef unsigned __int128 __u128 __attribute__((aligned(16)));
+#endif
+
+/*
+ * Below are truly Linux-specific types that should never collide with
+ * any application/library that wants linux/types.h.
+ */
+
+/* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */
+#ifdef __CHECKER__
+#define __bitwise	__attribute__((bitwise))
+#else
+#define __bitwise
+#endif
+
+/* The kernel doesn't use this legacy form, but user space does */
+#define __bitwise__ __bitwise
+
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
+typedef __u16 __bitwise __sum16;
+typedef __u32 __bitwise __wsum;
+
+/*
+ * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid
+ * common 32/64-bit compat problems.
+ * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other
+ * architectures) and to 8-byte boundaries on 64-bit architectures.  The new
+ * aligned_64 type enforces 8-byte alignment so that structs containing
+ * aligned_64 values have the same alignment on 32-bit and 64-bit architectures.
+ * No conversions are necessary between 32-bit user-space and a 64-bit kernel.
+ */
+#define __aligned_u64 __u64 __attribute__((aligned(8)))
+#define __aligned_be64 __be64 __attribute__((aligned(8)))
+#define __aligned_le64 __le64 __attribute__((aligned(8)))
+
+typedef unsigned __bitwise __poll_t;
+
+#endif /*  __ASSEMBLY__ */
+#endif /* _LINUX_TYPES_H */