net: amd-xgbe: add ARP offload and RSS self-tests
Subsystems (3)
Raju Rangoju
maintainercover net: amd-xgbe: add ARP offload and RSS self-tests
This series adds ARP offload support and ethtool self-tests for the AMD XGBE 10 Gigabit Ethernet driver.
Patch 1 adds hardware ARP offload functionality that allows the MAC to automatically respond to ARP requests without CPU intervention, reducing system latency and power consumption during suspend/resume and normal operation.
Patches 2 and 3 add ethtool self-tests for ARP offload and RSS functionality respectively, allowing users to verify these hardware features are working correctly via 'ethtool -t <interface>'.
The tests are integrated into the existing XGBE self-test framework that already includes MAC loopback, PHY loopback, split header, and jumbo frame tests.
Test results example:
$ ethtool -t eth0 The test result is PASS The test extra info: MAC Loopback 0 PHY Loopback 0 Split Header 0 Jumbo Frame 0 ARP Offload 0 RSS 0
Raju Rangoju (3):
net: amd-xgbe: add hardware ARP offload support
net: amd-xgbe: add ARP offload ethtool self-test
net: amd-xgbe: add RSS ethtool self-test
drivers/net/ethernet/amd/xgbe/xgbe-common.h | 3 + drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 24 +++ drivers/net/ethernet/amd/xgbe/xgbe-selftest.c | 149 ++++++++++++++++++ drivers/net/ethernet/amd/xgbe/xgbe.h | 4 + include/net/selftests.h | 1 + 5 files changed, 181 insertions(+)
Signature · 1 line
2.34.1
Raju Rangoju
maintainerPATCH 1/3 net: amd-xgbe: add hardware ARP offload support
Add ARP offload functionality to the XGBE driver that enables the MAC hardware to automatically respond to ARP requests without CPU intervention, reducing system latency and power consumption.
The XGBE MAC supports ARP offloading through:
- MAC_ARP_ADDR register (offset 0x0c10): stores the IPv4 address for which the hardware should respond to ARP requests
- ARPEN bit in MAC_RCR register (bit 31): enables/disables the ARP offload feature
When enabled, the MAC hardware will automatically generate ARP replies for requests targeting the configured IP address, without involving the host CPU.
The feature requires the aoe (ARP Offload Engine) hardware capability bit (ARPOFFSEL) to be set in the MAC_HWF0R register, which is checked before enabling.
--- drivers/net/ethernet/amd/xgbe/xgbe-common.h | 3 +++ drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 24 +++++++++++++++++++++ drivers/net/ethernet/amd/xgbe/xgbe.h | 4 ++++ 3 files changed, 31 insertions(+)
drivers/net/ethernet/amd/xgbe/xgbe-common.h +3 -0
@@ -210,6 +210,7 @@#define MAC_MACA0LR 0x0304#define MAC_MACA1HR 0x0308#define MAC_MACA1LR 0x030c +#define MAC_ARP_ADDR 0x0c10#define MAC_RSSCR 0x0c80#define MAC_RSSAR 0x0c88#define MAC_RSSDR 0x0c8c
@@ -400,6 +401,8 @@#define MAC_RCR_RE_WIDTH 1#define MAC_RCR_GPSL_INDEX 16#define MAC_RCR_GPSL_WIDTH 14 +#define MAC_RCR_ARPEN_INDEX 31 +#define MAC_RCR_ARPEN_WIDTH 1#define MAC_RFCR_PFCE_INDEX 8#define MAC_RFCR_PFCE_WIDTH 1#define MAC_RFCR_RFE_INDEX 0
drivers/net/ethernet/amd/xgbe/xgbe-dev.c +24 -0
@@ -3597,3 +3597,27 @@ void xgbe_disable_mac_loopback(struct xgbe_prv_data *pdata)/* Disable MAC loopback mode */ XGMAC_IOWRITE_BITS (pdata,MAC_RCR ,LM ,0 ); } + +/** +* xgbe_enable_arp_offload - Enable hardware ARP offload +* @pdata: pointer to driver private data +* @ip_addr: IPv4 address (in host byte order) to respond to ARP requests +* +* Configures the MAC to automatically respond to ARP requests for the +* specified IP address without CPU intervention. +*/ +void xgbe_enable_arp_offload (struct xgbe_prv_data *pdata,u32 ip_addr) +{ +XGMAC_IOWRITE (pdata,MAC_ARP_ADDR , ip_addr); +XGMAC_IOWRITE_BITS (pdata,MAC_RCR ,ARPEN ,1 ); +} + +/** +* xgbe_disable_arp_offload - Disable hardware ARP offload +* @pdata: pointer to driver private data +*/ +void xgbe_disable_arp_offload (struct xgbe_prv_data *pdata) +{ +XGMAC_IOWRITE_BITS (pdata,MAC_RCR ,ARPEN ,0 ); +XGMAC_IOWRITE (pdata,MAC_ARP_ADDR ,0 ); +}
drivers/net/ethernet/amd/xgbe/xgbe.h +4 -0
@@ -1333,6 +1333,10 @@ int xgbe_selftest_get_count(struct xgbe_prv_data *pdata);int xgbe_enable_mac_loopback (struct xgbe_prv_data *pdata);void xgbe_disable_mac_loopback (struct xgbe_prv_data *pdata); +/* ARP offload */ +void xgbe_enable_arp_offload (struct xgbe_prv_data *pdata,u32 ip_addr); +void xgbe_disable_arp_offload (struct xgbe_prv_data *pdata); +#ifdef CONFIG_DEBUG_FS void xgbe_debugfs_init (struct xgbe_prv_data *);void xgbe_debugfs_exit (struct xgbe_prv_data *);
Signature · 1 line
2.34.1
Raju Rangoju
maintainerPATCH 2/3 net: amd-xgbe: add ARP offload ethtool self-test
In reply to Raju RangojuAdd an ethtool self-test to verify the hardware ARP offload functionality. The test validates that the MAC correctly responds to ARP requests without CPU intervention.
Test procedure:
1. Check for aoe (ARP Offload Engine) hardware capability
2. Create an ARP request packet with test IP addresses
3. Enable ARP offload with the target IP address
4. Transmit the ARP request in PHY loopback mode
5. Verify that an ARP reply is received from the hardware
6. Clean up and restore configuration
The test requires the device to be in PHY loopback mode and runs as part of offline ethtool self-test suite.
Usage:
$ ethtool -t <interface>
--- drivers/net/ethernet/amd/xgbe/xgbe-selftest.c | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+)
drivers/net/ethernet/amd/xgbe/xgbe-selftest.c +117 -0
@@ -9,8 +9,10 @@#include <linux/crc32.h> #include <linux/ip.h> #include <linux/udp.h> +#include <linux/if_arp.h> #include <net/tcp.h> #include <net/udp.h> +#include <net/arp.h> #include <net/checksum.h> #include <net/selftests.h>
@@ -152,6 +154,117 @@ static int __xgbe_test_loopback(struct xgbe_prv_data *pdata,return ret; } +static int xgbe_test_arp_validate (struct sk_buff *skb, +struct net_device *ndev, +struct packet_type *pt, +struct net_device *orig_ndev) +{ +struct net_test_priv *tdata = pt->af_packet_priv; +struct ethhdr *eth_hdr; +struct arphdr *ah; + + skb =skb_unshare (skb,GFP_ATOMIC ); +if (!skb) + goto out; +if (skb_linearize (skb)) + goto out; + + eth_hdr = (struct ethhdr *)skb_mac_header (skb); + +/* Verify the reply is destined to our test source MAC */ +if (!ether_addr_equal_unaligned (eth_hdr->h_dest, tdata->packet->src)) + goto out; + +/* Verify this is an ARP packet */ +if (eth_hdr->h_proto !=htons (ETH_P_ARP )) + goto out; + + ah =arp_hdr (skb); + +/* Verify this is an ARP reply */ +if (ah->ar_op !=htons (ARPOP_REPLY )) + goto out; + + tdata->ok = true; +complete (&tdata->comp); +out: +kfree_skb (skb); +return 0 ; +} + +static int xgbe_test_arpoffload (struct xgbe_prv_data *pdata) +{ +unsigned char src[ETH_ALEN ] = {0x0a ,0x0b ,0x0c ,0x0d ,0x0e ,0x0f }; +unsigned char bcast[ETH_ALEN ] = {0xff ,0xff ,0xff ,0xff ,0xff ,0xff }; +struct net_packet_attrs attr = {}; +struct net_test_priv *tdata; +struct sk_buff *skb =NULL ; +u32 dst_ip =0xabcdefab ; +u32 src_ip =0xefdcbaef ; +int ret; + +/* Check if ARP offload is supported */ +if (!pdata->hw_feat.aoe) +return -EOPNOTSUPP ; + + tdata =kzalloc (sizeof (*tdata),GFP_KERNEL ); +if (!tdata) +return -ENOMEM ; + + tdata->ok = false; +init_completion (&tdata->comp); + + tdata->pt.type =htons (ETH_P_ARP ); + tdata->pt.func = xgbe_test_arp_validate; + tdata->pt.dev = pdata->netdev; + tdata->pt.af_packet_priv = tdata; + tdata->packet = &attr; +dev_add_pack (&tdata->pt); + + attr.src = src; + attr.ip_src = src_ip; + attr.dst = bcast; + attr.ip_dst = dst_ip; + +/* Create ARP request packet */ + skb =arp_create (ARPOP_REQUEST ,ETH_P_ARP ,htonl (dst_ip), + pdata->netdev,htonl (src_ip),NULL , src, bcast); +if (!skb) { + ret = -ENOMEM ; + goto free; + } + + skb->pkt_type =PACKET_HOST ; + skb->dev = pdata->netdev; + skb->protocol =htons (ETH_P_ARP ); + +/* Enable ARP offload */ +xgbe_enable_arp_offload (pdata, dst_ip); + + ret =dev_set_promiscuity (pdata->netdev,1 ); +if (ret) { +kfree_skb (skb); + goto cleanup; + } + + ret =dev_direct_xmit (skb,0 ); +if (ret) + goto cleanup_promisc; + +/* Wait for ARP reply */ +wait_for_completion_timeout (&tdata->comp,NET_LB_TIMEOUT ); + ret = tdata->ok ?0 : -ETIMEDOUT ; + +cleanup_promisc: +dev_set_promiscuity (pdata->netdev,-1 ); +cleanup: +xgbe_disable_arp_offload (pdata); +dev_remove_pack (&tdata->pt); +free: +kfree (tdata); +return ret; +} +static int xgbe_test_mac_loopback (struct xgbe_prv_data *pdata) {struct net_packet_attrs attr = {};
@@ -251,6 +364,10 @@ static const struct xgbe_test xgbe_selftests[] = { .name = "Jumbo Frame ", .lb = XGBE_LOOPBACK_PHY, .fn = xgbe_test_jumbo, + }, { + .name = "ARP Offload ", + .lb = XGBE_LOOPBACK_PHY, + .fn = xgbe_test_arpoffload, }, };
Signature · 1 line
2.34.1
kernel test robot
build botRe: [PATCH 2/3] net: amd-xgbe: add ARP offload ethtool self-test
kernel test robot noticed the following build errors:
Hi Raju,
kernel test robot noticed the following build errors:
[auto build test ERROR on net/main]
[also build test ERROR on net-next/main linus/master v6.19-rc8 next-20260202] [cannot apply to horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Raju-Rangoju/net-amd-xgbe-add-hardware-ARP-offload-support/20260202-235023 base: net/main patch link: https://lore.kernel.org/r/20260202153542.1727429-3-Raju.Rangoju%40amd.com patch subject: [PATCH 2/3] net: amd-xgbe: add ARP offload ethtool self-test config: powerpc-randconfig-002-20260203 (https://download.01.org/0day-ci/archive/20260203/[email protected]/config) compiler: powerpc-linux-gcc (GCC) 10.5.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260203/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
powerpc-linux-ld: drivers/net/ethernet/amd/xgbe/xgbe-selftest.o: in function `xgbe_test_arpoffload':
>> drivers/net/ethernet/amd/xgbe/xgbe-selftest.c:230: undefined reference to `arp_create'
powerpc-linux-ld: net/core/selftests.o: in function `net_test_get_skb':
net/core/selftests.c:104: undefined reference to `ip_send_check'
powerpc-linux-ld: net/core/selftests.c:148: undefined reference to `udp4_hwcsum'
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for HOTPLUG_CPU
Depends on [n]: SMP [=y] && (PPC_PSERIES [=n] || PPC_PMAC [=n] || PPC_POWERNV [=n] || FSL_SOC_BOOKE [=n])
Selected by [y]:
- PM_SLEEP_SMP [=y] && SMP [=y] && (ARCH_SUSPEND_POSSIBLE [=n] || ARCH_HIBERNATION_POSSIBLE [=y]) && PM_SLEEP [=y]
WARNING: unmet direct dependencies detected for NET_SELFTESTS
Depends on [n]: NET [=y] && PHYLIB [=y] && INET [=n]
Selected by [y]:
- AMD_XGBE [=y] && NETDEVICES [=y] && ETHERNET [=y] && NET_VENDOR_AMD [=y] && (OF_ADDRESS [=y] || ACPI || PCI [=n]) && HAS_IOMEM [=y] && (X86 || ARM64 || COMPILE_TEST [=y]) && PTP_1588_CLOCK_OPTIONAL [=y]
vim +230 drivers/net/ethernet/amd/xgbe/xgbe-selftest.c
194
195 static int xgbe_test_arpoffload(struct xgbe_prv_data *pdata)
196 {
197 unsigned char src[ETH_ALEN] = {0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
198 unsigned char bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
199 struct net_packet_attrs attr = {};
200 struct net_test_priv *tdata;
201 struct sk_buff *skb = NULL;
202 u32 dst_ip = 0xabcdefab;
203 u32 src_ip = 0xefdcbaef;
204 int ret;
205
206 /* Check if ARP offload is supported */
207 if (!pdata->hw_feat.aoe)
208 return -EOPNOTSUPP;
209
210 tdata = kzalloc(sizeof(*tdata), GFP_KERNEL);
211 if (!tdata)
212 return -ENOMEM;
213
214 tdata->ok = false;
215 init_completion(&tdata->comp);
216
217 tdata->pt.type = htons(ETH_P_ARP);
218 tdata->pt.func = xgbe_test_arp_validate;
219 tdata->pt.dev = pdata->netdev;
220 tdata->pt.af_packet_priv = tdata;
221 tdata->packet = &attr;
222 dev_add_pack(&tdata->pt);
223
224 attr.src = src;
225 attr.ip_src = src_ip;
226 attr.dst = bcast;
227 attr.ip_dst = dst_ip;
228
229 /* Create ARP request packet */
> 230 skb = arp_create(ARPOP_REQUEST, ETH_P_ARP, htonl(dst_ip),
231 pdata->netdev, htonl(src_ip), NULL, src, bcast);
232 if (!skb) {
233 ret = -ENOMEM;
234 goto free;
235 }
236
237 skb->pkt_type = PACKET_HOST;
238 skb->dev = pdata->netdev;
239 skb->protocol = htons(ETH_P_ARP);
240
241 /* Enable ARP offload */
242 xgbe_enable_arp_offload(pdata, dst_ip);
243
244 ret = dev_set_promiscuity(pdata->netdev, 1);
245 if (ret) {
246 kfree_skb(skb);
247 goto cleanup;
248 }
249
250 ret = dev_direct_xmit(skb, 0);
251 if (ret)
252 goto cleanup_promisc;
253
254 /* Wait for ARP reply */
255 wait_for_completion_timeout(&tdata->comp, NET_LB_TIMEOUT);
256 ret = tdata->ok ? 0 : -ETIMEDOUT;
257
258 cleanup_promisc:
259 dev_set_promiscuity(pdata->netdev, -1);
260 cleanup:
261 xgbe_disable_arp_offload(pdata);
262 dev_remove_pack(&tdata->pt);
263 free:
264 kfree(tdata);
265 return ret;
266 }
267
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Jakub Kicinski
maintainerRe: [2/3] net: amd-xgbe: add ARP offload ethtool self-test
In reply to Raju RangojuThis is an AI-generated review of your patch. The human sending this email has considered the AI review valid, or at least plausible.
For local reproduction steps see https://netdev-ai.bots.linux.dev/ai-local.html
---
net: amd-xgbe: add ARP offload ethtool self-test
This patch adds an ethtool self-test to verify the hardware ARP offload functionality. The test creates an ARP request, enables ARP offload, and verifies the hardware responds with an ARP reply.
Quoted 3 lines
drivers/net/ethernet/amd/xgbe/xgbe-selftest.c +0
-0
[ ... ]
Quoted 2 lines
drivers/net/ethernet/amd/xgbe/xgbe-selftest.c +2
-0+static int xgbe_test_arpoffload (struct xgbe_prv_data *pdata) +{
[ ... ]
Quoted 6 lines
drivers/net/ethernet/amd/xgbe/xgbe-selftest.c +6
-0+ tdata->pt.type =htons (ETH_P_ARP ); + tdata->pt.func = xgbe_test_arp_validate; + tdata->pt.dev = pdata->netdev; + tdata->pt.af_packet_priv = tdata; + tdata->packet = &attr; +dev_add_pack (&tdata->pt);
[ ... ]
drivers/net/ethernet/amd/xgbe/xgbe-selftest.c static int __xgbe_test_loopback(struct xgbe_prv_data *pdata, · line 235
Quoted 7 lines
drivers/net/ethernet/amd/xgbe/xgbe-selftest.c +7
-0+/* Create ARP request packet */ + skb =arp_create (ARPOP_REQUEST ,ETH_P_ARP ,htonl (dst_ip), + pdata->netdev,htonl (src_ip),NULL , src, bcast); +if (!skb) { + ret = -ENOMEM ; + goto free; + }
Can this cause a use-after-free? The packet handler is registered via dev_add_pack() before arp_create() is called. When arp_create() fails, 'goto free' jumps directly to kfree(tdata) without calling dev_remove_pack(&tdata->pt).
This leaves the packet handler registered with a dangling pointer (tdata->pt.af_packet_priv = tdata). When any ARP packet subsequently arrives, xgbe_test_arp_validate() is called and dereferences freed memory:
struct net_test_priv *tdata = pt->af_packet_priv;
...
if (!ether_addr_equal_unaligned(eth_hdr->h_dest, tdata->packet->src))Should 'goto free' be changed to 'goto cleanup' here to ensure dev_remove_pack() is called?
Signature · 1 line
pw-bot: cr
Raju Rangoju
maintainerPATCH 3/3 net: amd-xgbe: add RSS ethtool self-test
In reply to Raju RangojuAdd a Receive Side Scaling (RSS) self-test to the ethtool diagnostic suite to verify that the hardware correctly computes hash values for incoming packets.
The test validates RSS functionality by:
1. Checking for RSS hardware feature support (rss bit in MAC_HWF1R)
2. Sending a test packet with specific TCP/UDP ports to trigger hash computation
3. Verifying that the received packet has a non-zero hash value computed by the hardware
The test uses the existing loopback infrastructure and requires PHY loopback mode. It uses specific port values (sport=0xabc, dport=0xdef) to generate a deterministic hash that exercises the RSS hash computation logic.
This test helps users verify that RSS is properly configured and functioning, which is essential for multi-queue performance on multi-core systems.
Usage:
$ ethtool -t <interface>
--- drivers/net/ethernet/amd/xgbe/xgbe-selftest.c | 32 +++++++++++++++++++ include/net/selftests.h | 1 + 2 files changed, 33 insertions(+)
drivers/net/ethernet/amd/xgbe/xgbe-selftest.c +32 -0
@@ -100,8 +100,13 @@ static int xgbe_test_loopback_validate(struct sk_buff *skb,if (tdata->packet->id != hdr->id) goto out; +/* Validate RSS hash if expected */ +if (tdata->packet->exp_hash && !skb->hash) + goto out; + tdata->ok = true;complete (&tdata->comp); + out:kfree_skb (skb);return 0 ;
@@ -154,6 +159,29 @@ static int __xgbe_test_loopback(struct xgbe_prv_data *pdata,return ret; } +static int xgbe_test_rss (struct xgbe_prv_data *pdata) +{ +struct net_packet_attrs attr = {}; +int ret; + +/* Check for RSS hardware support */ +if (!pdata->hw_feat.rss) +return -EOPNOTSUPP ; + + attr.dst = pdata->netdev->dev_addr; +/* +* Use specific port values to generate a hash. +* The asymmetric port values ensure the hash computation +* produces a non-zero result for test validation. +*/ + attr.sport =0xabc ; + attr.dport =0xdef ; + attr.exp_hash = true; + ret =__xgbe_test_loopback (pdata, &attr); + +return ret; +} + static int xgbe_test_arp_validate(struct sk_buff *skb, struct net_device *ndev, struct packet_type *pt,
@@ -368,6 +396,10 @@ static const struct xgbe_test xgbe_selftests[] = { .name = "ARP Offload ", .lb = XGBE_LOOPBACK_PHY, .fn = xgbe_test_arpoffload, + }, { + .name = "RSS Hash ", + .lb = XGBE_LOOPBACK_PHY, + .fn = xgbe_test_rss, }, };
include/net/selftests.h +1 -0
@@ -19,6 +19,7 @@ struct net_packet_attrs {u8 id;u16 queue_mapping;bool bad_csum; +u32 exp_hash; };struct net_test_priv {
Signature · 1 line
2.34.1