Pete Batard
2016-Feb-24 13:02 UTC
[syslinux] [PATCH 2/5] ntfs: remove unused variable and have ntfssect use char API calls
The variable 'ok' is never used and generates a warning. Remove it. Also ntfssect.c is designed to be compiled in non Unicode mode when using MSVC compilers, so remove all ambiguity about it (LPCTSTR -> LPCSTR, use of 'A' API calls) so that it doesn't break when compiled in Unicode mode, which is what Rufus uses with MSVC. -------------- next part --------------
Shao Miller
2016-Feb-24 23:43 UTC
[syslinux] [PATCH 2/5] ntfs: remove unused variable and have ntfssect use char API calls
On 2/24/2016 08:02, Pete Batard via Syslinux wrote:> The variable 'ok' is never used and generates a warning. Remove it. Also > ntfssect.c is designed to be compiled in non Unicode mode when using > MSVC compilers, so remove all ambiguity about it (LPCTSTR -> LPCSTR, use > of 'A' API calls) so that it doesn't break when compiled in Unicode > mode, which is what Rufus uses with MSVC. >Did you happen to notice anything unusual when compiling with MinGW under Linux, once 'ok' was removed? I seem to recall warnings about unused results, but not of unused objects. Maybe that's an incorrect recollection or maybe it's ancient history, however. - Shao Miller Synthetel : https://www.synthetel.com
Pete Batard
2016-Feb-25 12:30 UTC
[syslinux] [PATCH 2/5] ntfs: remove unused variable and have ntfssect use char API calls
Hi Shao, On 2016.02.24 23:43, Shao Miller via Syslinux wrote:> Did you happen to notice anything unusual when compiling with MinGW > under Linux, once 'ok' was removed? I seem to recall warnings about > unused results, but not of unused objects. Maybe that's an incorrect > recollection or maybe it's ancient history, however.I got no warnings with the patch on Debian 8 + MinGW-w64. Here's the relevant compilation excerpt: make[3]: Entering directory '/usr/src/syslinux/bios/win64' x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o syslinux.obj /usr/src/syslinux/win64/../win/syslinux.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o ntfssect.obj /usr/src/syslinux/win64/../win/ntfssect.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o fs.obj /usr/src/syslinux/win64/../libinstaller/fs.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o syslxmod.obj /usr/src/syslinux/win64/../libinstaller/syslxmod.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o syslxopt.obj /usr/src/syslinux/win64/../libinstaller/syslxopt.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o setadv.obj /usr/src/syslinux/win64/../libinstaller/setadv.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o getopt_long.obj /usr/src/syslinux/win64/../libinstaller/getopt/getopt_long.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o bootsect_bin.obj /usr/src/syslinux/bios/win64/../libinstaller/bootsect_bin.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o ldlinux_bin.obj /usr/src/syslinux/bios/win64/../libinstaller/ldlinux_bin.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o ldlinuxc32_bin.obj /usr/src/syslinux/bios/win64/../libinstaller/ldlinuxc32_bin.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o mbr_bin.obj /usr/src/syslinux/bios/win64/../libinstaller/mbr_bin.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o cache.obj /usr/src/syslinux/win64/../libfat/cache.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o fatchain.obj /usr/src/syslinux/win64/../libfat/fatchain.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o open.obj /usr/src/syslinux/win64/../libfat/open.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o searchdir.obj /usr/src/syslinux/win64/../libfat/searchdir.c rm -f syslinux.lib x86_64-w64-mingw32-ar cq syslinux.lib fs.obj syslxmod.obj syslxopt.obj setadv.obj getopt_long.obj bootsect_bin.obj ldlinux_bin.obj ldlinuxc32_bin.obj mbr_bin.obj cache.obj fatchain.obj open.obj searchdir.obj x86_64-w64-mingw32-ranlib syslinux.lib x86_64-w64-mingw32-gcc -Os -s -o syslinux64.exe syslinux.obj ntfssect.obj syslinux.lib make[3]: Leaving directory '/usr/src/syslinux/bios/win64' Regards, /Pete
Hi guys,
I have re-implemented /efi/udp.c
The new code fixes:
1) The low and decreasing throughput on TFTP transfers.
2) The added delay between consecutive TFTP transfers.
3) The TFTP errors induced by broadcast traffic like ARP.
Initial tests on a 50MB transfer showed times going from 3 minutes
to ~12 seconds, also tested OK with nested TFTP transfers
(include command).
This new code affects/fixes the problems reported at:
a) "Problem with 90MB Initrd"
http://www.syslinux.org/archives/2015-September/024236.html
b) "UEFI: Failed to load ldlinux.e64/ldlinux.e32"
http://www.syslinux.org/archives/2015-October/024341.html
This report has led to Gene's patch:
https://github.com/geneC/syslinux/commit/9e0926bb338deb5c634ccb4ee29eb4577158cfdc
it was reported working but I think "it cannot work" if it has these
lines
+ memcpy(&udata.StationAddress, &IPInfo.myip, sizeof(IPInfo.myip));
+ memcpy(&udata.StationAddress, &IPInfo.netmask,
sizeof(IPInfo.netmask));
the StationAddress gets overwritten by a netmask...
There's a picture attached comparing performance between the old and new
udp.c code.
Testing reports are welcome.
Best,
Patrick
Signed-off-by: Patrick Masotta <masottaus at yahoo.com>
diff -uprN a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h
--- a/core/fs/pxe/pxe.h 2014-10-06 10:27:44.000000000 -0600
+++ b/core/fs/pxe/pxe.h 2016-02-28 08:44:47.127996962 -0700
@@ -130,6 +130,7 @@ union net_private {
struct net_private_efi {
struct efi_binding *binding; /* EFI binding for protocol */
uint16_t localport; /* Local port number (0=not in use) */
+ void* context; /* Holds the UDP_IO Instance (used in the new efi
UDP codebase) */
} efi;
};
diff -uprN a/efi/udp.c b/efi/udp.c
--- a/efi/udp.c 2014-10-06 10:27:44.000000000 -0600
+++ b/efi/udp.c 2016-02-28 08:41:29.867226806 -0700
@@ -1,5 +1,6 @@
/*
- * Copyright 2013-2014 Intel Corporation - All Rights Reserved
+ * Serva (c) 2010-2016 Patrick Masotta - All Rights Reserved
+ *
*/
#include <string.h>
@@ -8,50 +9,189 @@
#include "net.h"
#include "fs/pxe/pxe.h"
+
+#define TICKS_PER_SECOND 10000000
+#define TICKS_PER_MS 10000
+
+#define UDP_TIME_TO_GETMAP 5 * TICKS_PER_SECOND
+#define UDP_TIME_TX_TIMEOUT 1 * TICKS_PER_SECOND + 500 * TICKS_PER_MS
+#define UDP_TIME_RX_TIMEOUT 1 * TICKS_PER_SECOND + 500 * TICKS_PER_MS
+
+
+///
+/// Type defined as RX.
+/// This data structure wraps receive udp parameters.
+///
+typedef struct {
+ void* buf;
+ uint16_t* buf_len;
+ uint32_t* src_ip;
+ uint16_t* src_port;
+}RX;
+
+///
+/// Type defined as UDP_IO.
+/// This data structure wraps the UDP instance and configuration.
+///
+typedef struct {
+ uint16_t known_TID;
+ struct efi_binding* b;
+ EFI_UDP4* Protocol_Udp4;
+ EFI_UDP4_CONFIG_DATA Config_Udp4;
+ EFI_UDP4_COMPLETION_TOKEN* Token;
+ EFI_EVENT Timeout_Timer;
+ EFI_EVENT CB_OK_Event;
+ RX rx;
+}UDP_IO;
+
+
+#define EFI_IP4_EQUAL(Ip1, Ip2) (CompareMem ((Ip1), (Ip2), sizeof
(EFI_IPv4_ADDRESS)) == 0)
+EFI_IPv4_ADDRESS mZeroIp4Addr = {{0, 0, 0, 0}};
+static BOOLEAN volatile UseDefaultSetting = TRUE;
+
extern EFI_GUID Udp4ServiceBindingProtocol, Udp4Protocol;
-/*
- * This UDP binding is configured to operate in promiscuous mode. It is
- * only used for reading packets. It has no associated state unlike
- * socket->net.efi.binding, which has a remote IP address and port
- * number.
- */
-static struct efi_binding *udp_reader;
+
+
+
+/**
+ Poll the UDP to get the IP4 default address, which may be retrieved
+ by DHCP.
+
+ The default time out value is 5 seconds. If IP has retrieved the default
address,
+ the UDP is reconfigured.
+
+
+ @param udp_io The UDP_IO instance
+ @param udata The UDP configure data to reconfigure the UDP_IO
+
+ @retval TRUE The default address is retrieved and UDP is
reconfigured.
+ @retval FALSE Some error occured.
+
+**/
+BOOLEAN
+efi_udp_get_mapping (UDP_IO* udp_io, EFI_UDP4_CONFIG_DATA* udata)
+{
+ EFI_STATUS status;
+ EFI_UDP4* udp;
+ EFI_IP4_MODE_DATA Ip4Mode;
+
+// ASSERT (UseDefaultSetting);
+
+ udp = udp_io->Protocol_Udp4;
+
+ status = uefi_call_wrapper( BS->SetTimer, 3,
+ udp_io->Timeout_Timer,
+ TimerRelative,
+ UDP_TIME_TO_GETMAP
+ );
+
+ if (EFI_ERROR (status))
+ return FALSE;
+
+ while (EFI_ERROR ( uefi_call_wrapper(BS->CheckEvent, 1,
udp_io->Timeout_Timer) ))
+ {
+ udp->Poll(udp);
+
+ if (!EFI_ERROR(udp->GetModeData(udp, NULL, &Ip4Mode, NULL, NULL))
&&
+ Ip4Mode.IsConfigured)
+ {
+ udp->Configure(udp, NULL);
+ return (BOOLEAN) (udp->Configure(udp, udata) == EFI_SUCCESS);
+ }
+ }
+
+ return FALSE;
+}
+
+
/**
- * Try to configure this UDP socket
+ * Try to configure this UDP_IO
*
- * @param:udp, the EFI_UDP4 socket to configure
- * @param:udata, the EFI_UDP4_CONFIG_DATA to use
- * @param:f, the name of the function as a wide string.
+ * @param:udp_io, The UDP_IO containing the EFI_UDP4 socket to configure
+ * and the EFI_UDP4_CONFIG_DATA to use.
+ * @param:f, The name of the invoking function as a wide string.
*
* @out: status as EFI_STATUS
*/
-
-EFI_STATUS core_udp_configure(EFI_UDP4 *udp, EFI_UDP4_CONFIG_DATA *udata,
- short unsigned int *f)
+EFI_STATUS efi_udp_configure(UDP_IO *udp_io, short unsigned int *f)
{
- EFI_STATUS status;
- int unmapped = 1;
- jiffies_t start, last, cur;
-
- last = start = jiffies();
- while (unmapped){
- status = uefi_call_wrapper(udp->Configure, 2, udp, udata);
- if (status != EFI_NO_MAPPING)
- unmapped = 0;
- else {
- cur = jiffies();
- if ( (cur - last) >= EFI_NOMAP_PRINT_DELAY ) {
- last = cur;
- Print(L"%s: stalling on configure with no mapping\n", f);
- } else if ( (cur - start) > EFI_NOMAP_PRINT_DELAY *
EFI_NOMAP_PRINT_COUNT) {
- Print(L"%s: aborting on no mapping\n", f);
- unmapped = 0;
- }
- }
- }
- return status;
+
+ EFI_STATUS status;
+ EFI_UDP4* udp = udp_io->Protocol_Udp4;
+ EFI_UDP4_CONFIG_DATA* udata = &udp_io->Config_Udp4;
+
+
+ status = uefi_call_wrapper(udp->Configure, 2, udp, NULL);
+ if (EFI_ERROR (status))
+ {
+ return status;
+ }
+
+
+ status= uefi_call_wrapper(udp->Configure, 2, udp, udata);
+ if( status == EFI_SUCCESS )
+ {
+ EFI_STATUS status;
+
+ status = uefi_call_wrapper(udp->GetModeData, 5, udp,
+ udata, NULL, NULL, NULL);
+
+ if(status == EFI_SUCCESS )
+ return EFI_SUCCESS;
+ else
+ return -1;
+ }
+
+ else
+ if ( status == EFI_NO_MAPPING &&
+ UseDefaultSetting &&
+ efi_udp_get_mapping (udp_io, udata) &&
+ EFI_SUCCESS == uefi_call_wrapper(udp->GetModeData, 5, udp,
+ udata, NULL, NULL, NULL)
+ )
+ return EFI_SUCCESS;
+ else
+ if(
+ UseDefaultSetting &&
+ !EFI_IP4_EQUAL (&mZeroIp4Addr, &IPInfo.gateway) &&
+ !EFI_IP4_EQUAL (&mZeroIp4Addr, &IPInfo.myip) &&
+ !EFI_IP4_EQUAL (&mZeroIp4Addr, &IPInfo.netmask)
+ )
+ { // udp->Configure() and efi_udp_get_mapping() failed lets try a manual
config
+ EFI_STATUS status;
+
+ UseDefaultSetting=FALSE;
+ udata->UseDefaultAddress = FALSE;
+ memcpy(&udata->StationAddress , &IPInfo.myip,
sizeof(IPInfo.myip));
+ memcpy(&udata->SubnetMask, &IPInfo.netmask,
sizeof(IPInfo.netmask));
+
+ status = uefi_call_wrapper(udp->Routes , 5,
+ udp,
+ FALSE,
+ &mZeroIp4Addr,
+ &mZeroIp4Addr,
+ (EFI_IPv4_ADDRESS *)&IPInfo.gateway
+ );
+ if (EFI_ERROR (status))
+ {
+ uefi_call_wrapper(udp->Configure, 2, udp, NULL);
+ return -1;
+ }
+
+ if( EFI_ERROR (uefi_call_wrapper(udp->Configure, 2, udp, NULL)) ||
+ EFI_ERROR (uefi_call_wrapper(udp->Configure, 2, udp, udata))
+ )
+ return -1;
+ else
+ return EFI_SUCCESS;
+
+ }
+
+ else
+ return -1;
+
}
/**
@@ -63,55 +203,76 @@ EFI_STATUS core_udp_configure(EFI_UDP4 *
*/
int core_udp_open(struct pxe_pvt_inode *socket)
{
- EFI_UDP4_CONFIG_DATA udata;
- struct efi_binding *b;
- EFI_STATUS status;
- EFI_UDP4 *udp;
-
+ EFI_STATUS status;
+ struct efi_binding* b;
+ EFI_UDP4* udp;
+ UDP_IO* udp_io;
+
(void)socket;
- udp_reader = efi_create_binding(&Udp4ServiceBindingProtocol,
&Udp4Protocol);
- if (!udp_reader)
- return -1;
-
- b = efi_create_binding(&Udp4ServiceBindingProtocol, &Udp4Protocol);
- if (!b)
- goto bail;
-
- udp = (EFI_UDP4 *)udp_reader->this;
-
- memset(&udata, 0, sizeof(udata));
-
- status = core_udp_configure(udp, &udata, L"core_udp_open");
- if (status != EFI_SUCCESS)
- goto bail;
-
- socket->net.efi.binding = b;
-
- /*
- * Save the random local port number that the UDPv4 Protocol
- * Driver picked for us. The TFTP protocol uses the local port
- * number as the TID.
- */
- status = uefi_call_wrapper(udp->GetModeData, 5, udp,
- &udata, NULL, NULL, NULL);
- if (status != EFI_SUCCESS)
- Print(L"Failed to get UDP mode data: %d\n", status);
- else
- socket->net.efi.localport = udata.StationPort;
+
+ b = efi_create_binding(&Udp4ServiceBindingProtocol, &Udp4Protocol);
+ if(!b)
+ return -1;
+
+ udp_io=zalloc(sizeof(UDP_IO));
+ if(!udp_io)
+ goto bail;
+
+ udp_io->b = b;
+
+ udp = (EFI_UDP4 *)b->this;
+ udp_io->Protocol_Udp4 = udp;
+
+ socket->net.efi.context = udp_io;
+
+ //
+ // Create the timer used to time out transmit, receive, and get map events
+ //
+ status = uefi_call_wrapper(BS->CreateEvent, 5,
+ EVT_TIMER,
+ TPL_CALLBACK,
+ NULL,
+ NULL,
+ &udp_io->Timeout_Timer
+ );
+ if (EFI_ERROR (status))
+ goto bail;
+
+ //
+ // Create the event to signal when the send/receive callback function ends
+ // correctly.
+ //
+ status = uefi_call_wrapper(BS->CreateEvent, 5,
+ EVT_TIMER,
+ TPL_CALLBACK,
+ NULL,
+ NULL,
+ &udp_io->CB_OK_Event
+ );
+ if (EFI_ERROR (status))
+ goto bail;
return 0;
bail:
if (b)
- efi_destroy_binding(b, &Udp4ServiceBindingProtocol);
+ efi_destroy_binding(b, &Udp4ServiceBindingProtocol);
- efi_destroy_binding(udp_reader, &Udp4ServiceBindingProtocol);
- udp_reader = NULL;
+ if(udp_io && udp_io->Timeout_Timer)
+ uefi_call_wrapper(BS->CloseEvent, 1, udp_io->Timeout_Timer);
+
+ if(udp_io && udp_io->CB_OK_Event)
+ uefi_call_wrapper(BS->CloseEvent, 1, udp_io->CB_OK_Event);
+
+
+ if(udp_io)
+ free(udp_io);
return -1;
}
+
/**
* Close a socket
*
@@ -119,299 +280,394 @@ bail:
*/
void core_udp_close(struct pxe_pvt_inode *socket)
{
- efi_destroy_binding(udp_reader, &Udp4ServiceBindingProtocol);
- udp_reader = NULL;
- if (!socket->net.efi.binding)
- return;
-
- efi_destroy_binding(socket->net.efi.binding,
&Udp4ServiceBindingProtocol);
- socket->net.efi.binding = NULL;
+ UDP_IO* udp_io;
+ udp_io = (UDP_IO*)socket->net.efi.context;
+
+
+ if (!udp_io->b)
+ return;
+
+ efi_destroy_binding(udp_io->b, &Udp4ServiceBindingProtocol);
+ udp_io->b = NULL;
+
+ if(udp_io->Timeout_Timer)
+ uefi_call_wrapper(BS->CloseEvent, 1, udp_io->Timeout_Timer);
+
+ if(udp_io->CB_OK_Event)
+ uefi_call_wrapper(BS->CloseEvent, 1, udp_io->CB_OK_Event);
+
+ if(socket->net.efi.context)
+ free(socket->net.efi.context);
+ socket->net.efi.context=NULL;
+
+
}
/**
* Establish a connection on an open socket
*
- * @param:socket, the open socket
- * @param:ip, the ip address
- * @param:port, the port number, host-byte order
+ * @param:socket, the open socket
+ * @param:ip, the source ip address
+ * @param:port, the source port number, host-byte order
*/
-void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t ip,
- uint16_t port)
+void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t src_ip,
+ uint16_t src_port)
{
- EFI_UDP4_CONFIG_DATA udata;
- EFI_STATUS status;
- EFI_UDP4 *udp;
-
- udp = (EFI_UDP4 *)socket->net.efi.binding->this;
- memset(&udata, 0, sizeof(udata));
-
- /* Re-use the existing local port number */
- udata.StationPort = socket->net.efi.localport;
-
- udata.UseDefaultAddress = TRUE;
- memcpy(&udata.RemoteAddress, &ip, sizeof(ip));
- udata.RemotePort = port;
- udata.AcceptPromiscuous = TRUE;
- udata.TimeToLive = 64;
-
- status = core_udp_configure(udp, &udata,
L"core_udp_connect");
- if (status != EFI_SUCCESS) {
- Print(L"Failed to configure UDP: %d\n", status);
- return;
- }
+ EFI_STATUS status;
+ UDP_IO* udp_io;
+
+ udp_io = (UDP_IO*)socket->net.efi.context;
+
+ if ( src_port != udp_io->Config_Udp4.RemotePort )
+ {
+ udp_io->Config_Udp4.RemotePort = src_port;
+
+ status = efi_udp_configure(udp_io, L"core_udp_connect");
+ if (EFI_ERROR (status))
+ {
+ Print(L"Failed to configure UDP: %d\n", status);
+ return;
+ }
+ }
+
}
/**
* Tear down a connection on an open socket
*
- * @param:socket, the open socket
+ * @param:socket, the open socket
*/
void core_udp_disconnect(struct pxe_pvt_inode *socket)
{
- EFI_STATUS status;
- EFI_UDP4 *udp;
-
- udp = (EFI_UDP4 *)socket->net.efi.binding->this;
-
- /* Reset */
- status = uefi_call_wrapper(udp->Configure, 2, udp, NULL);
- if (status != EFI_SUCCESS)
- Print(L"Failed to reset UDP: %d\n", status);
+
+ return;
+
}
-static int volatile cb_status = -1;
-static EFIAPI void udp4_cb(EFI_EVENT event, void *context)
-{
- (void)event;
-
- EFI_UDP4_COMPLETION_TOKEN *token = context;
- if (token->Status == EFI_SUCCESS)
- cb_status = 0;
- else
- cb_status = 1;
+/**
+ *
+ * Send callback function
+ *
+ */
+VOID
+EFIAPI
+UdpIoOnDgramSent (
+ IN EFI_EVENT event,
+ IN VOID* context
+ )
+{
+ UDP_IO* udp_io;
+ EFI_UDP4_COMPLETION_TOKEN* token;
+
+ udp_io = (UDP_IO*) context;
+ if( udp_io &&
+ (token = udp_io->Token) &&
+ token->Status == EFI_SUCCESS
+ )
+ uefi_call_wrapper(BS->SignalEvent, 1, udp_io->CB_OK_Event);
}
+
/**
- * Read data from the network stack
+ * Send a UDP packet (blocking call).
*
- * @param:socket, the open socket
- * @param:buf, location of buffer to store data
- * @param:buf_len, size of buffer
-
- * @out: src_ip, ip address of the data source
- * @out: src_port, port number of the data source, host-byte order
+ * @param:socket, the open socket
+ * @param:data, data buffer to send
+ * @param:len, size of data bufer
*/
-int core_udp_recv(struct pxe_pvt_inode *socket, void *buf, uint16_t *buf_len,
- uint32_t *src_ip, uint16_t *src_port)
+
+void core_udp_send(struct pxe_pvt_inode *socket, const void *data, size_t len)
{
- EFI_UDP4_COMPLETION_TOKEN token;
- EFI_UDP4_FRAGMENT_DATA *frag;
- EFI_UDP4_RECEIVE_DATA *rxdata;
- struct efi_binding *b;
EFI_STATUS status;
- EFI_UDP4 *udp;
- size_t size;
- int rv = -1;
- jiffies_t start;
-
- (void)socket;
-
- b = udp_reader;
- udp = (EFI_UDP4 *)b->this;
- memset(&token, 0, sizeof(token));
-
- status = efi_setup_event(&token.Event, (EFI_EVENT_NOTIFY)udp4_cb,
- &token);
- if (status != EFI_SUCCESS)
- return -1;
-
- status = uefi_call_wrapper(udp->Receive, 2, udp, &token);
- if (status != EFI_SUCCESS)
- goto bail;
-
- start = jiffies();
- while (cb_status == -1) {
- /* 15ms receive timeout... */
- if (jiffies() - start >= 15) {
- if (jiffies() - start >= 30)
- dprintf("Failed to cancel UDP\n");
-
- uefi_call_wrapper(udp->Cancel, 2, udp, &token);
- dprintf("core_udp_recv: timed out\n");
- }
+ UDP_IO* udp_io;
+ EFI_UDP4* udp;
+ EFI_UDP4_COMPLETION_TOKEN* token=NULL;
+ EFI_UDP4_TRANSMIT_DATA* txdata=NULL;
+ EFI_UDP4_FRAGMENT_DATA* frag;
- uefi_call_wrapper(udp->Poll, 1, udp);
- }
+ udp_io = (UDP_IO*)socket->net.efi.context;
+ udp = udp_io->Protocol_Udp4;
- if (cb_status == 0)
- rv = 0;
- /* Reset */
- cb_status = -1;
-
- if (rv)
- goto bail;
-
- rxdata = token.Packet.RxData;
- frag = &rxdata->FragmentTable[0];
+ token = zalloc(sizeof(EFI_UDP4_COMPLETION_TOKEN));
+ if (!token)
+ goto bail;
- size = min(frag->FragmentLength, *buf_len);
- memcpy(buf, frag->FragmentBuffer, size);
- *buf_len = size;
+ txdata = zalloc(sizeof(EFI_UDP4_TRANSMIT_DATA));
+ if (!txdata)
+ goto bail;
- memcpy(src_port, &rxdata->UdpSession.SourcePort, sizeof(*src_port));
- memcpy(src_ip, &rxdata->UdpSession.SourceAddress, sizeof(*src_ip));
+ status = efi_setup_event(&token->Event,
(EFI_EVENT_NOTIFY)UdpIoOnDgramSent,
+ udp_io);
+ if (EFI_ERROR (status))
+ goto bail;
- uefi_call_wrapper(BS->SignalEvent, 1, rxdata->RecycleSignal);
-bail:
- uefi_call_wrapper(BS->CloseEvent, 1, token.Event);
- return rv;
-}
+ udp_io->Token = token;
-/**
- * Send a UDP packet.
- *
- * @param:socket, the open socket
- * @param:data, data buffer to send
- * @param:len, size of data bufer
- */
-void core_udp_send(struct pxe_pvt_inode *socket, const void *data, size_t len)
-{
- EFI_UDP4_COMPLETION_TOKEN *token;
- EFI_UDP4_TRANSMIT_DATA *txdata;
- EFI_UDP4_FRAGMENT_DATA *frag;
- struct efi_binding *b = socket->net.efi.binding;
- EFI_STATUS status;
- EFI_UDP4 *udp = (EFI_UDP4 *)b->this;
-
- token = zalloc(sizeof(*token));
- if (!token)
- return;
-
- txdata = zalloc(sizeof(*txdata));
- if (!txdata) {
- free(token);
- return;
- }
-
- status = efi_setup_event(&token->Event, (EFI_EVENT_NOTIFY)udp4_cb,
- token);
- if (status != EFI_SUCCESS)
- goto bail;
-
- txdata->DataLength = len;
- txdata->FragmentCount = 1;
+ txdata->DataLength = len;
+ txdata->FragmentCount = 1;
+
frag = &txdata->FragmentTable[0];
-
frag->FragmentLength = len;
frag->FragmentBuffer = (void *)data;
token->Packet.TxData = txdata;
-
+
+ status = uefi_call_wrapper(BS->SetTimer, 3,
+ udp_io->Timeout_Timer,
+ TimerRelative,
+ UDP_TIME_TX_TIMEOUT
+ );
+ if (EFI_ERROR (status))
+ goto bail;
+
+ uefi_call_wrapper(BS->CheckEvent, 1, udp_io->CB_OK_Event);
status = uefi_call_wrapper(udp->Transmit, 2, udp, token);
- if (status != EFI_SUCCESS)
- goto close;
+ if (EFI_ERROR (status))
+ {
+ goto close;
+ }
- while (cb_status == -1)
- uefi_call_wrapper(udp->Poll, 1, udp);
+
+ while (1)
+ {
+ uefi_call_wrapper(udp->Poll, 1, udp);
+
+ if(!EFI_ERROR ( uefi_call_wrapper(BS->CheckEvent, 1,
udp_io->CB_OK_Event) ))
+ {
+ goto close; //TX OK
+ }
+
+ if(!EFI_ERROR ( uefi_call_wrapper(BS->CheckEvent, 1,
udp_io->Timeout_Timer) ))
+ {
+ dprintf("core_udp_send: timed out\n");
+ goto close; //TX timeout
+ }
+ }
- /* Reset */
- cb_status = -1;
close:
uefi_call_wrapper(BS->CloseEvent, 1, token->Event);
bail:
- free(txdata);
- free(token);
+ if(txdata)
+ free(txdata);
+
+ if(token)
+ free(token);
+
+ udp_io->Token = NULL;
}
+
+
/**
* Send a UDP packet to a destination
*
- * @param:socket, the open socket
- * @param:data, data buffer to send
- * @param:len, size of data bufer
- * @param:ip, the ip address
- * @param:port, the port number, host-byte order
+ * @param:socket, the open socket
+ * @param:data, data buffer to send
+ * @param:len, size of data bufer
+ * @param:ip, the remote ip address
+ * @param:port, the remote port number, host-byte order
*/
void core_udp_sendto(struct pxe_pvt_inode *socket, const void *data,
- size_t len, uint32_t ip, uint16_t port)
+ size_t len, uint32_t remote_ip, uint16_t remote_port)
{
- EFI_UDP4_COMPLETION_TOKEN *token;
- EFI_UDP4_TRANSMIT_DATA *txdata;
- EFI_UDP4_FRAGMENT_DATA *frag;
- EFI_UDP4_CONFIG_DATA udata;
- EFI_STATUS status;
- struct efi_binding *b;
- EFI_UDP4 *udp;
+ EFI_STATUS status;
+ UDP_IO* udp_io;
- (void)socket;
- b = efi_create_binding(&Udp4ServiceBindingProtocol, &Udp4Protocol);
- if (!b)
- return;
+ udp_io = (UDP_IO*)socket->net.efi.context;
+
+ if(!udp_io->known_TID)
+ udp_io->known_TID=remote_port;
+
+ udp_io->Config_Udp4.AcceptBroadcast = FALSE;
+ udp_io->Config_Udp4.AcceptPromiscuous = FALSE;
+ udp_io->Config_Udp4.AcceptAnyPort = FALSE;
+ udp_io->Config_Udp4.AllowDuplicatePort = FALSE;
+ udp_io->Config_Udp4.TypeOfService = 0;
+ udp_io->Config_Udp4.TimeToLive = 64;
+ udp_io->Config_Udp4.DoNotFragment = FALSE;
+ udp_io->Config_Udp4.ReceiveTimeout = 0;
+ udp_io->Config_Udp4.TransmitTimeout = 0;
+
+
+ if (UseDefaultSetting)
+ {
+ udp_io->Config_Udp4.UseDefaultAddress = TRUE;
+ }
+ else
+ {
+ udp_io->Config_Udp4.UseDefaultAddress = FALSE;
+ memcpy(&udp_io->Config_Udp4.StationAddress , &IPInfo.myip,
sizeof(IPInfo.myip));
+ memcpy(&udp_io->Config_Udp4.SubnetMask, &IPInfo.netmask,
sizeof(IPInfo.netmask));
+ }
+
+ //udp_io->Config_Udp4.StationPort = 0; //Reuse or initially
assigned by FW
+
+ memcpy(&udp_io->Config_Udp4.RemoteAddress, &remote_ip,
sizeof(remote_ip));
+ udp_io->Config_Udp4.RemotePort = remote_port;
+
+
+ status = efi_udp_configure(udp_io, L"core_udp_sendto");
+ if (EFI_ERROR (status))
+ return;
+
+ core_udp_send(socket, data, len);
- udp = (EFI_UDP4 *)b->this;
+}
- token = zalloc(sizeof(*token));
- if (!token)
- goto out;
+
+
+/**
+ *
+ * Receive callback function
+ *
+ */
+VOID
+EFIAPI
+UdpIoOnDgramRecvd (
+ IN EFI_EVENT event,
+ IN VOID* context
+ )
+{
+ UDP_IO* udp_io;
+ EFI_UDP4_COMPLETION_TOKEN* token;
+ EFI_UDP4_FRAGMENT_DATA* frag;
+ EFI_UDP4_RECEIVE_DATA* rxdata;
+
+ size_t size;
+
+ udp_io = (UDP_IO*) context;
+
+ if( udp_io &&
+ (token = udp_io->Token) &&
+ token->Status == EFI_SUCCESS
+ )
+ {
+ rxdata = token->Packet.RxData;
+ frag = &rxdata->FragmentTable[0];
+
+ size = min(frag->FragmentLength, *(udp_io->rx.buf_len));
+ memcpy(udp_io->rx.buf, frag->FragmentBuffer, size);
+ *(udp_io->rx.buf_len) = size;
+
+ memcpy(udp_io->rx.src_port, &rxdata->UdpSession.SourcePort,
sizeof(*udp_io->rx.src_port));
+ memcpy(udp_io->rx.src_ip, &rxdata->UdpSession.SourceAddress,
sizeof(*udp_io->rx.src_ip));
+
+ uefi_call_wrapper(BS->SignalEvent, 1, rxdata->RecycleSignal);
+
+ uefi_call_wrapper(BS->SignalEvent, 1, udp_io->CB_OK_Event);
+
+ }
+
+}
- txdata = zalloc(sizeof(*txdata));
- if (!txdata)
- goto bail;
-
- memset(&udata, 0, sizeof(udata));
-
- /* Re-use the existing local port number */
- udata.StationPort = socket->net.efi.localport;
-
- udata.UseDefaultAddress = TRUE;
- memcpy(&udata.RemoteAddress, &ip, sizeof(ip));
- udata.RemotePort = port;
- udata.AcceptPromiscuous = TRUE;
- udata.TimeToLive = 64;
-
- status = core_udp_configure(udp, &udata, L"core_udp_sendto");
- if (status != EFI_SUCCESS)
- goto bail;
-
- status = efi_setup_event(&token->Event, (EFI_EVENT_NOTIFY)udp4_cb,
- token);
- if (status != EFI_SUCCESS)
- goto bail;
- txdata->DataLength = len;
- txdata->FragmentCount = 1;
- frag = &txdata->FragmentTable[0];
+/**
+ * Read data from the network stack (blocking call)
+ *
+ * @param:socket, the open socket
+ * @param:buf, location of buffer to store data
+ * @param:buf_len, size of buffer
- frag->FragmentLength = len;
- frag->FragmentBuffer = (void *)data;
+ * @out:src_ip, ip address of the data source
+ * @out:src_port, port number of the data source, host-byte order
+ */
+
+int core_udp_recv(struct pxe_pvt_inode *socket, void *buf, uint16_t *buf_len,
+ uint32_t *src_ip, uint16_t *src_port)
+{
+ EFI_STATUS status;
+ UDP_IO* udp_io;
+ EFI_UDP4* udp;
+ EFI_UDP4_COMPLETION_TOKEN* token;
+ int rv = -1;
- token->Packet.TxData = txdata;
- status = uefi_call_wrapper(udp->Transmit, 2, udp, token);
- if (status != EFI_SUCCESS)
- goto close;
+ udp_io = (UDP_IO*)socket->net.efi.context;
+ udp = udp_io->Protocol_Udp4;
+
+ token = zalloc(sizeof(EFI_UDP4_COMPLETION_TOKEN));
+
+ if (!token)
+ return -1;
- while (cb_status == -1)
- uefi_call_wrapper(udp->Poll, 1, udp);
- /* Reset */
- cb_status = -1;
+ status = efi_setup_event(&token->Event,
(EFI_EVENT_NOTIFY)UdpIoOnDgramRecvd,
+ udp_io);
+ if (EFI_ERROR (status))
+ goto bail;
+
+
+ udp_io->Token = token;
+
+ udp_io->rx.buf = buf;
+ udp_io->rx.buf_len = buf_len;
+ udp_io->rx.src_ip = src_ip;
+ udp_io->rx.src_port = src_port;
+
+ status = uefi_call_wrapper( BS->SetTimer, 3,
+ udp_io->Timeout_Timer,
+ TimerRelative,
+ UDP_TIME_RX_TIMEOUT
+ );
+ if (EFI_ERROR (status))
+ goto bail;
+
+ if( udp_io->Config_Udp4.RemotePort == udp_io->known_TID )
+ {
+ udp_io->Config_Udp4.RemotePort=0;
+ status = efi_udp_configure(udp_io, L"core_udp_recv");
+ if (EFI_ERROR (status))
+ goto bail;
+ }
+
+ uefi_call_wrapper(BS->CheckEvent, 1, udp_io->CB_OK_Event);
+
+ status = uefi_call_wrapper(udp->Receive, 2, udp, token);
+ if (EFI_ERROR (status))
+ goto bail;
+
+ while (1)
+ {
+ uefi_call_wrapper(udp->Poll, 1, udp);
+
+
+ if(!EFI_ERROR ( uefi_call_wrapper(BS->CheckEvent, 1,
udp_io->CB_OK_Event) ))
+ {
+ rv = 0;
+ goto close; //RX OK
+ }
+
+ if( ( EFI_SUCCESS == uefi_call_wrapper(BS->CheckEvent, 1,
udp_io->Timeout_Timer)) )
+ {
+ uefi_call_wrapper(udp->Cancel, 2, udp, token);
+ dprintf("core_udp_recv: timed out\n");
+ rv = -1;
+ goto bail; //RX timeout
+ }
+
+ }
-close:
- uefi_call_wrapper(BS->CloseEvent, 1, token->Event);
+close:
+
bail:
- free(txdata);
- free(token);
-out:
- efi_destroy_binding(b, &Udp4ServiceBindingProtocol);
+ uefi_call_wrapper(BS->CloseEvent, 1, token->Event);
+
+ if(token)
+ free(token);
+
+ udp_io->Token=NULL;
+
+ return rv;
}
+
+
-------------- next part --------------
A non-text attachment was scrubbed...
Name: UEFI UDP compare-.png
Type: image/png
Size: 70861 bytes
Desc: not available
URL:
<http://www.zytor.com/pipermail/syslinux/attachments/20160228/a7d90d8d/attachment-0001.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: efi_udp.patch
Type: application/octet-stream
Size: 24996 bytes
Desc: not available
URL:
<http://www.zytor.com/pipermail/syslinux/attachments/20160228/a7d90d8d/attachment-0001.obj>
Patrick Masotta via Syslinux <syslinux at zytor.com> writes:> There's a picture attached comparing performance between the old and > new udp.c code.Impressive! -- Regards, Feri.
On Sun, Feb 28, 2016 at 04:26:07PM +0000, Patrick Masotta via Syslinux wrote:> > > I have re-implemented /efi/udp.c> Signed-off-by: Patrick Masotta <masottaus at yahoo.com> > > diff -uprN a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h > --- a/core/fs/pxe/pxe.h 2014-10-06 10:27:44.000000000 -0600 > +++ b/core/fs/pxe/pxe.h 2016-02-28 08:44:47.127996962 -0700 > @@ -130,6 +130,7 @@ union net_private { > struct net_private_efi { > struct efi_binding *binding; /* EFI binding for protocol */ > uint16_t localport; /* Local port number (0=not in use) */ > + void* context; /* Holds the UDP_IO Instance (used in the new efi UDP codebase) */ > } efi; > }; > > diff -uprN a/efi/udp.c b/efi/udp.c > --- a/efi/udp.c 2014-10-06 10:27:44.000000000 -0600 > +++ b/efi/udp.c 2016-02-28 08:41:29.867226806 -0700 > @@ -1,5 +1,6 @@ > /* > - * Copyright 2013-2014 Intel Corporation - All Rights Reserved > + * Serva (c) 2010-2016 Patrick Masotta - All Rights Reserved > + * > */ > > #include <string.h> > @@ -8,50 +9,189 @@ > #include "net.h" > #include "fs/pxe/pxe.h" > > + > +#define TICKS_PER_SECOND 10000000 > +#define TICKS_PER_MS 10000 > + > +#define UDP_TIME_TO_GETMAP 5 * TICKS_PER_SECOND > +#define UDP_TIME_TX_TIMEOUT 1 * TICKS_PER_SECOND + 500 * TICKS_PER_MS > +#define UDP_TIME_RX_TIMEOUT 1 * TICKS_PER_SECOND + 500 * TICKS_PER_MS<snip/>> > /** > - * Try to configure this UDP socket > + * Try to configure this UDP_IO > * > - * @param:udp, the EFI_UDP4 socket to configure > - * @param:udata, the EFI_UDP4_CONFIG_DATA to use > - * @param:f, the name of the function as a wide string. > + * @param:udp_io, The UDP_IO containing the EFI_UDP4 socket to configure > + * and the EFI_UDP4_CONFIG_DATA to use. > + * @param:f, The name of the invoking function as a wide string. > * > * @out: status as EFI_STATUS > */ > - > -EFI_STATUS core_udp_configure(EFI_UDP4 *udp, EFI_UDP4_CONFIG_DATA *udata, > - short unsigned int *f) > +EFI_STATUS efi_udp_configure(UDP_IO *udp_io, short unsigned int *f) > { > } > > /** > * Establish a connection on an open socket > * > - * @param:socket, the open socket > - * @param:ip, the ip address > - * @param:port, the port number, host-byte order > + * @param:socket, the open socketWhite space change> + * @param:ip, the source ip addressWhite space change, plus 'source '> + * @param:port, the source port number, host-byte orderWhite space change, plus 'source '> */ > -void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t ip, > - uint16_t port) > +void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t src_ip, > + uint16_t src_port)Changed 'ip' and 'port' in 'src_ip' and 'src_port'. However: 'src_ip' and 'src_port' are not in } + * @param:ip, the source ip address } + * @param:port, the source port number, host-byte order <snip/>> -static EFIAPI void udp4_cb(EFI_EVENT event, void *context) > +VOID > +EFIAPI > +UdpIoOnDgramSent ( > + IN EFI_EVENT event, > + IN VOID* context > + )Such coding style change did me really stop removing this unified patch. Groeten Geert Stappers -- Leven en laten leven ------------- volgend deel ------------ Een niet-tekst bijlage is gescrubt... Naam: signature.asc Type: application/pgp-signature Grootte: 836 bytes Omschrijving: Digital signature URL : <http://www.zytor.com/pipermail/syslinux/attachments/20160228/0593b013/attachment.sig>
On Sun, Feb 28, 2016 at 11:26 AM, Patrick Masotta via Syslinux <syslinux at zytor.com> wrote:> b) "UEFI: Failed to load ldlinux.e64/ldlinux.e32" > http://www.syslinux.org/archives/2015-October/024341.html > This report has led to Gene's patch: > > https://github.com/geneC/syslinux/commit/9e0926bb338deb5c634ccb4ee29eb4577158cfdc > it was reported working but I think "it cannot work" if it has these lines > > + memcpy(&udata.StationAddress, &IPInfo.myip, sizeof(IPInfo.myip)); > + memcpy(&udata.StationAddress, &IPInfo.netmask, sizeof(IPInfo.netmask)); > > the StationAddress gets overwritten by a netmask...Thanks for noticing. I've corrected this and I'm reviewing the patch itself. -- -Gene