summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2024-03-18 16:21:04 +0100
committerMichael Brown2024-03-18 23:52:05 +0100
commit926816c58fca5641b17c17379b52203458081668 (patch)
tree38ce87537bad17468f7351ada5bea2179075e4ef
parent[golan] Use ETH_HLEN for inline header size (diff)
downloadipxe-926816c58fca5641b17c17379b52203458081668.tar.gz
ipxe-926816c58fca5641b17c17379b52203458081668.tar.xz
ipxe-926816c58fca5641b17c17379b52203458081668.zip
[efi] Pad transmit buffer length to work around vendor driver bugs
The Mellanox/Nvidia UEFI driver is built from the same codebase as the iPXE driver, and appears to contain the bug that was fixed in commit c11734e ("[golan] Use ETH_HLEN for inline header size"). This results in identical failures when using the SNP or NII interface (via e.g. snponly.efi) to drive a Mellanox card while EAPoL is enabled. Work around the underlying UEFI driver bug by padding transmit I/O buffers to the minimum Ethernet frame length before passing them to the underlying driver's transmit function. This padding is not technically necessary, since almost all modern hardware will insert transmit padding as necessary (and where the hardware does not support doing so, the underlying UEFI driver is responsible for adding any necessary padding). However, it is guaranteed to be harmless (other than a miniscule performance impact): the Ethernet specification requires zero padding up to the minimum frame length for packets that are transmitted onto the wire, and so the receiver will see the same packet whether or not we manually insert this padding in software. The additional padding causes the underlying Mellanox driver to avoid its faulty code path, since it will never be asked to transmit a very short packet. Tested-by: Eric Hagberg <ehagberg@janestreet.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/drivers/net/efi/nii.c7
-rw-r--r--src/drivers/net/efi/snpnet.c7
2 files changed, 14 insertions, 0 deletions
diff --git a/src/drivers/net/efi/nii.c b/src/drivers/net/efi/nii.c
index 8dd17e4b..16e9e10d 100644
--- a/src/drivers/net/efi/nii.c
+++ b/src/drivers/net/efi/nii.c
@@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <errno.h>
#include <ipxe/netdevice.h>
#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
#include <ipxe/umalloc.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_driver.h>
@@ -998,6 +999,12 @@ static int nii_transmit ( struct net_device *netdev,
return 0;
}
+ /* Pad to minimum Ethernet length, to work around underlying
+ * drivers that do not correctly handle frame padding
+ * themselves.
+ */
+ iob_pad ( iobuf, ETH_ZLEN );
+
/* Construct parameter block */
memset ( &cpb, 0, sizeof ( cpb ) );
cpb.FrameAddr = ( ( intptr_t ) iobuf->data );
diff --git a/src/drivers/net/efi/snpnet.c b/src/drivers/net/efi/snpnet.c
index c66aa7d2..b8bf963e 100644
--- a/src/drivers/net/efi/snpnet.c
+++ b/src/drivers/net/efi/snpnet.c
@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/iobuf.h>
#include <ipxe/netdevice.h>
#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
#include <ipxe/vsprintf.h>
#include <ipxe/timer.h>
#include <ipxe/efi/efi.h>
@@ -187,6 +188,12 @@ static int snpnet_transmit ( struct net_device *netdev,
return 0;
}
+ /* Pad to minimum Ethernet length, to work around underlying
+ * drivers that do not correctly handle frame padding
+ * themselves.
+ */
+ iob_pad ( iobuf, ETH_ZLEN );
+
/* Transmit packet */
if ( ( efirc = snp->snp->Transmit ( snp->snp, 0, iob_len ( iobuf ),
iobuf->data, NULL, NULL,