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