On Mon, Jul 27, 2015 at 05:52:48AM +0000, Fu, Siyuan wrote:
> Hi, Michael
> 
> Can you help to test whether this patch could solve your problem?

Yes. It works for me. :)

Thanks,
Michael

> 
> Thanks,
> Siyuan
> 
> -----Original Message-----
> From: Michael Chang [mailto:mch...@suse.com] 
> Sent: Friday, July 24, 2015 10:34 AM
> To: Fu, Siyuan
> Cc: edk2-devel@lists.sourceforge.net; Ye, Ting
> Subject: Re: [edk2] DHCPv6 IAID and NetRandomInitSeed problem in OVMF
> 
> On Thu, Jul 23, 2015 at 10:13:20AM +0000, Fu, Siyuan wrote:
> > Michael,
> > 
> > It's not because any benefit, it's because there is actually no place to 
> > put the static local variable. The IaDescriptor.IaId is defined in UEFI 
> > spec, so Dhcp6->Configure() function could only use caller provided IaId 
> > number and can't modify it. And we couldn't use static local variable in 
> > NetLib, because the library is statically linked to IP6 and PXE driver, so 
> > there are actually 2 static variable in these 2 driver.
> > 
> 
> Thank you for the explaination, now I understood why. If you have any patch 
> for this and need testing, please let me know and I'm glad to help.
> 
> Thanks,
> Michael
> 
> > Best Regards
> > Siyuan
> > 
> > -----Original Message-----
> > From: Michael Chang [mailto:mch...@suse.com]
> > Sent: Thursday, July 23, 2015 5:43 PM
> > To: Fu, Siyuan
> > Cc: edk2-devel@lists.sourceforge.net; Ye, Ting
> > Subject: Re: [edk2] DHCPv6 IAID and NetRandomInitSeed problem in OVMF
> > 
> > On Thu, Jul 23, 2015 at 09:01:38AM +0000, Fu, Siyuan wrote:
> > > Hi, Michael
> > > 
> > > It's indeed a problem that NET_RANDOM (NetRandomInitSeed ()) may return 
> > > same value if the time service is not accuracy enough on some platform. 
> > > And as you said it's used to give unique but not necessarily to be real 
> > > random number, so I think we could just add some salt into the seed. I 
> > > think the platform monotonic counter may be a good choose, we can call 
> > > gBS->GetNextMonotonicCount() and add the low 32 bits of MC to the seed. 
> > > This could make the returned seed unique even GetTime() return all zero 
> > > in the worst case. What do you think about it?
> > 
> > It sounds good for me. But I'd like to know what is the benefit compared to 
> > increment by static local variable?
> > 
> > > 
> > > For your recommendation #3, the IaId is configured by Ip6Dxe and PXE 
> > > driver, and there are no interface to exchange the index between them. 
> > > DHCP6 driver just use the IaId configured by caller and it couldn't 
> > > modify it. And for 4, one of the design intention of PXE boot is 
> > > "platform doesn't need any pre-configuration", so it's also not 
> > > acceptable.
> > 
> > Actually I'm not sure about the need to create automatic policy. Is there 
> > any function or feature in UEFI preboot environment depend on it to work 
> > correctly (likely it is for booting iSCSI disks, but that can be done in 
> > other settings) ?
> > 
> > Thanks,
> > Michael
> > 
> > > 
> > > Best Regards,
> > > Siyuan
> > > 
> > > -----Original Message-----
> > > From: Michael Chang [mailto:mch...@suse.com]
> > > Sent: Thursday, July 23, 2015 3:33 PM
> > > To: edk2-devel@lists.sourceforge.net
> > > Subject: [edk2] DHCPv6 IAID and NetRandomInitSeed problem in OVMF
> > > 
> > > Hi,
> > > 
> > > I have problem in IPv6 PXE booting under OVMF that the process terminated 
> > > immediately right after selecting the UEFI IPv6 boot entry. I have to 
> > > change the IPv6 config policy from automatic to manual to get things 
> > > working again for me.
> > > 
> > > I looked a bit into this problem, it was terminated by the error in 
> > > IaId check
> > > 
> > >  in NetworkPkg/Dhcp6Dxe/Dhcp6Impl.c::EfiDhcp6Configure function
> > >     
> > >     //
> > >     // Make sure the (IaId, IaType) is unique over all the instances.
> > >     //
> > >     NET_LIST_FOR_EACH (Entry, &Service->Child) {
> > >       Other = NET_LIST_USER_STRUCT (Entry, DHCP6_INSTANCE, Link);
> > >       if (Other->IaCb.Ia != NULL &&
> > >           Other->IaCb.Ia->Descriptor.Type == 
> > > Dhcp6CfgData->IaDescriptor.Type &&
> > >           Other->IaCb.Ia->Descriptor.IaId == 
> > > Dhcp6CfgData->IaDescriptor.IaId
> > >           ) {
> > >         return EFI_INVALID_PARAMETER;
> > >       }
> > >     }
> > > 
> > > Which would be saying clearly it was not "unique" among all the 
> > > running
> > > DHCPv6 instances. At that time there should be only two:
> > > 
> > > 1. The IPv6 config instance, while the policy is set to automatic 
> > > would exchange information with server with the IaId initialized at
> > > 
> > >   NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c::Ip6ConfigInitInstance
> > > 
> > >     Instance->IaId = NET_RANDOM (NetRandomInitSeed ());
> > > 
> > >     for (Index = 0; Index < IpSb->SnpMode.HwAddressSize; Index++) {
> > >       Instance->IaId |= (IpSb->SnpMode.CurrentAddress.Addr[Index] << 
> > > ((Index << 3) & 31));
> > >     }
> > > 
> > > 2. The IPv6 PXE Base code driver would start another DHCPv6 session 
> > > with the IaId initialized at
> > > 
> > >   NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c::PxeBcCreateIp6Children
> > > 
> > >   //
> > >   // Generate a random IAID for the Dhcp6 assigned address.
> > >   //
> > >   Private->IaId = NET_RANDOM (NetRandomInitSeed ());
> > >   if (Private->Snp != NULL) {
> > >     for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) {
> > >       Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << 
> > > ((Index << 3) & 31));
> > >     }
> > >   }
> > > 
> > > Unfortunately both IaId collides, and quite surprisingly it's NET_RANDOM 
> > > (NetRandomInitSeed ()), or NetRandomInitSeed () generates the same number 
> > > for them.
> > > 
> > > UINT32
> > > EFIAPI
> > > NetRandomInitSeed (
> > >   VOID
> > >   )
> > > {
> > >   EFI_TIME                  Time;
> > >   UINT32                    Seed;
> > > 
> > >   gRT->GetTime (&Time, NULL);
> > >   Seed = (~Time.Hour << 24 | Time.Day << 16 | Time.Minute << 8 | 
> > > Time.Second);
> > >   Seed ^= Time.Nanosecond;
> > >   Seed ^= Time.Year << 7;
> > > 
> > >   return Seed;
> > > }
> > > 
> > > The returned Time.Nanosecond is always zero as the timer resolution is l 
> > > Hz for PC-AT CMOS RTC, that seems to be default real time clock driver 
> > > used by OVMF. At least from .dsc file it says so ..
> > > 
> > >   
> > > PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeD
> > > xe
> > > .inf
> > > 
> > > The NetRandomInitSeed is not random enough in this case, and the 
> > > NET_RANDOM marco is even more confusing as it's not a random number 
> > > generator either (so what is good for always feeding random "seed" 
> > > to a deterministic mathematic fucntion ??)
> > > 
> > > I don't have good idea how to fix the problem, but here are of my thoughs.
> > > 
> > > 1. Use real timer clock driver which could provide higher resolution for 
> > > time service. Qemu is able to provide HPET timer but I don't know how to 
> > > configure OVMF to use it.
> > > 
> > > 2. Use GetPerformanceCounter(), but that would increase image size by 
> > > linking TimerLib.
> > > 
> > > 3. The IaId has to be "unique" thus not necessarily to be random, 
> > > probably it should be derived by some properties like MAC address and an 
> > > assgined index (staring from zero) for the interface to be confiured.
> > > 
> > > 4. Use manual as default IPv6 policy, but that just hide the problem.
> > > 
> > > Hope that my information and findings helps. :)
> > > 
> > > Thanks,
> > > Michael
> > > 
> > > --------------------------------------------------------------------
> > > --
> > > -------- _______________________________________________
> > > edk2-devel mailing list
> > > edk2-devel@lists.sourceforge.net
> > > https://lists.sourceforge.net/lists/listinfo/edk2-devel

> Date: Mon, 27 Jul 2015 05:51:20 +0000
> From: "Fu, Siyuan" <siyuan...@intel.com>
> To: "edk2-de...@lists.01.org" <edk2-de...@lists.01.org>
> Subject: [edk2] [Patch] MdeModulePkg: Use monotonic count to initialize the
>  NetLib random seed.
> 
> NetRandomInitSeed() function use current time to initialize the random seed,
> while in some platform the time service is not accuracy that make the random
> seed collision. This patch add the monotonic count to the seed to avoid this.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Fu Siyuan <siyuan...@intel.com>
> ---
>  MdeModulePkg/Include/Library/NetLib.h      | 10 +++++-----
>  MdeModulePkg/Library/DxeNetLib/DxeNetLib.c | 12 ++++++++----
>  2 files changed, 13 insertions(+), 9 deletions(-)
> 
> diff --git a/MdeModulePkg/Include/Library/NetLib.h 
> b/MdeModulePkg/Include/Library/NetLib.h
> index 7ad8dac..280c51a 100644
> --- a/MdeModulePkg/Include/Library/NetLib.h
> +++ b/MdeModulePkg/Include/Library/NetLib.h
> @@ -528,17 +528,17 @@ NetPutUint32 (
>    IN OUT UINT8                 *Buf,
>    IN     UINT32                Data
>    );
> 
>  /**
> -  Initialize a random seed using current time.
> +  Initialize a random seed using current time and monotonic count.
> 
> -  Get current time first. Then initialize a random seed based on some basic
> -  mathematical operations on the hour, day, minute, second, nanosecond and 
> year
> -  of the current time.
> +  Get current time and monotonic count first. Then initialize a random seed
> +  based on some basic mathematics operation on the hour, day, minute, second,
> +  nanosecond and year of the current time and the monotonic count value.
> 
> -  @return The random seed, initialized with current time.
> +  @return The random seed initialized with current time.
> 
>  **/
>  UINT32
>  EFIAPI
>  NetRandomInitSeed (
> diff --git a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c 
> b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
> index ce26b32..57e8f9f 100644
> --- a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
> +++ b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
> @@ -851,15 +851,15 @@ Ip6Swap128 (
> 
>    return Ip6;
>  }
> 
>  /**
> -  Initialize a random seed using current time.
> +  Initialize a random seed using current time and monotonic count.
> 
> -  Get current time first. Then initialize a random seed based on some basic
> -  mathematics operation on the hour, day, minute, second, nanosecond and year
> -  of the current time.
> +  Get current time and monotonic count first. Then initialize a random seed
> +  based on some basic mathematics operation on the hour, day, minute, second,
> +  nanosecond and year of the current time and the monotonic count value.
> 
>    @return The random seed initialized with current time.
> 
>  **/
>  UINT32
> @@ -868,16 +868,20 @@ NetRandomInitSeed (
>    VOID
>    )
>  {
>    EFI_TIME                  Time;
>    UINT32                    Seed;
> +  UINT64                    MonotonicCount;
> 
>    gRT->GetTime (&Time, NULL);
>    Seed = (~Time.Hour << 24 | Time.Day << 16 | Time.Minute << 8 | 
> Time.Second);
>    Seed ^= Time.Nanosecond;
>    Seed ^= Time.Year << 7;
> 
> +  gBS->GetNextMonotonicCount (&MonotonicCount);
> +  Seed += (UINT32) MonotonicCount;
> +
>    return Seed;
>  }
> 
> 
>  /**
> --
> 1.9.5.msysgit.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-de...@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel

------------------------------------------------------------------------------
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to