Hi Gary,

On 04/01/14 09:30, Gary Ching-Pang Lin wrote:
> Hi,
> 
> I am using OVMF to test OS PXE installation. The function basically
> works except the transmission rate of tftp is much lower than expected.
> 
> Here is my setup:
> 
> A virtual net device, tap0, was created to connect the host and the guest
> in QEMU like this:
> 
>  [ HOST ] ---- [tap0] ---- [ guest ]
> dhcp server               OVMF r15416
> tftp server
>  ftp server
> 
> Here is my command to create the virtual machine:
> qemu-system-x86_64 -s -bios <path ot ovmf> -drive file=disk.img,if=virtio \
>   -m 1024 -enable-kvm -fsdev 
> local,id=exp,path=share,security_model=mapped-file \
>   -device virtio-9p-pci,fsdev=exp,mount_tag=v_share -monitor stdio \
>   -debugcon file:debug.log -global isa-debugcon.iobase=0x402 \
>   -netdev tap,id=vmnet0,ifname=tap0,script=no,downscript=no -device 
> virtio-net-pci,netdev=vmnet0
> 
> The host runs openSUSE 13.1, and I use dnsmasq to set up the dhcp and
> tftp servers for the preboot images and a ftp server for the installation
> of packages.
> 
> The boot procedure is:
> 
> [OVMF] -> [shim.efi] -> [grub.efi] -> [Linux kernel + initrd] -> 
> [Installation]
> 
> I noticed the slowness while grub2 loading the kernel and initrd. The two
> files are 50~60 MB in total, and grub2 took 8~10 minutes to finish loading.
> Then I used tcpdump to capture packets through tap0 and found the transmission
> rate was just 1~2 Mbits/s.
> 
> I switched the firmware to SeaBIOS and changed the boot procedure to
> 
> [SeaBIOS] -> [grub2] -> [Linux kernel + initrd] -> [Installation]
> 
> It took only seconds to load the kernel and initrd.
> 
> I also tried the proprietary e1000 EFI driver, and the result was the same.
> Did anyone also have the slow tftp issue?

Yes.

There are two (possible) reasons to consider.


(1) The first possible reason is the frequency of the timer, which (if I
understand correctly) provides the ticks for the higher level network
drivers. In OVMF we use "PcAtChipsetPkg/8254TimerDxe".

For example, whenever I tested the DataSource test app (from AppPkg),
the best speed it achieved (between guest and host, mind you) was
280-300KB/s (about 200 packets/s). This seems to be limited by the timer
resolution.

(I always used TCP in this app, so there might have been other factors
at play.)

The "default timer tick duration is set to 10 ms" (see near
DEFAULT_TIMER_TICK_DURATION in "PcAtChipsetPkg/8254TimerDxe/Timer.h").

Unfortunately, there doesn't seem to be a PCD for this. Also, we can't
just call the EFI_TIMER_ARCH_PROTOCOL.SetTimerPeriod() member function
ourselves, in platform code, because the PI spec vol2 says:

    12.10 Timer Architectural Protocol
    EFI_TIMER_ARCH_PROTOCOL

    Summary

    Used to set up a periodic timer interrupt using a platform specific
    timer, and a processor-specific interrupt vector. This protocol
    enables the use of the SetTimer() Boot Service. This protocol
    must be produce by a boot service or runtime DXE driver and may
    only be consumed by the DXE Foundation or DXE drivers that produce
    other DXE Architectural Protocols.

The HPET flavor (PcAtChipsetPkg/HpetTimerDxe) *is* controllable with a
PCD (PcdHpetDefaultTimerPeriod), but in OVMF we don't use that. (AFAIR
qemu has some problems with HPET emulation, but I'm not fully sure.)


(2) The second possible reason is a grub2 bug which has bitten us before.

Importantly, you are using grub2's PXE and TFTP clients, not the ones
built into edk2 (UefiPxeBcDxe and Mtftp4Dxe under
MdeModulePkg/Universal/Network/).

If I remember correctly our earlier analysis, grub2 opens the SNP
interface without kicking off other consumers of the service; notably,
ARP (MdeModulePkg/Universal/Network/ArpDxe).

The result is that the edk2 ARP driver and grub2's TFTP client compete
for incoming packets. The ARP driver steals some packets, and throws off
grub2's TFTP client.

The idea is that grub2 should open SNP with the EXCLUSIVE attribute:

    If Attributes is [...] EXCLUSIVE, and there is an item on the open
    list of the protocol interface with an attribute of BY_DRIVER, then
    the boot service DisconnectController() is called for the driver on
    the open list. [...]

and

    EXCLUSIVE  Used by applications to gain exclusive access to a
               protocol interface. If any drivers have the protocol
               interface opened with an attribute of BY_DRIVER, then an
               attempt will be made to remove them by calling the
               driver’s Stop() function.

Please try the attached grub2 patch. (Note: I'm not sure this was the
final patch that we ended up with.)


If fiddling with DEFAULT_TIMER_TICK_DURATION in (1) helps, then we
should submit a patch for PcAtChipsetPkg that adds a PCD, similar to
PcdHpetDefaultTimerPeriod, for 8254TimerDxe.

Thanks
Laszlo
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index 2b344d6..d775e7b 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -164,7 +164,7 @@ grub_efinet_findcards (void)
       struct grub_net_card *card;
 
       net = grub_efi_open_protocol (*handle, &net_io_guid,
-				    GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+				    GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE);
       if (! net)
 	/* This should not happen... Why?  */
 	continue;
------------------------------------------------------------------------------
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to