Tuesday, May 26, 2015

How to check for Second Level Address Translation with Powershell

Not so long ago Microsoft added Client Hyper-V virtualization technology to its last OS, Windows 8. This move has given ITPros and developers like me the possibility to test the Hyper-V technology on their laptops and build test infrastructures aimed at learning, making demos and developing management scripts.

Now, most of the requirements to run the Hyper-V Client on your Windows 8.1 laptop are pretty simple to check. You need to own a 64-bit Pro or Enterprise version of Microsoft Windows, 4 GB of RAM and a processor (either AMD or Intel) with 64-bit wide registers. All of these requirement are easy to check.

There is one more requirement which is harder to check and to understand: your processor must, I repeat, MUST be able to perform Second Level Address Translation (SLAT).

What is that?

POPEK AND GOLDBERG AND THE DIFFICULTY OF VIRTUALISING X86

It's a long story that starts way back in 1964, when virtualization was born with the arrival of the first IBM/360 mainframe and a lot of efforts were put into optimizing environments upon which enterprises could rely . In 1974, when virtualization was already a pretty widely applied technique in the world of mainframe computing, computer scientists  Gerald J. Popek and Robert P. Goldberg published the three principles of computer virtualization we all know today:
  • fidelity/equivalence
  • safety/resource control
  • performance/efficiency
They basically mean that the executed virtual machine must be able to run as fast as a physical machine, act in the same way of a physical machine and never get out of the control of the virtual machine monitor (VMM).

Requirements for a virtual machine
(extract from 'Formal requirements for virtualizable third generation architectures'
by Popek and Goldberg
1974)
These three requirements were extremely hard to respect, largely because of the inner nature of x86 processors, which copes badly (read: doesn't cope at all) with the trap-and-emulate schema.

FROM BINARY TRANSLATION TO SLAT

Through Binary Translation, Shadow Page Tables and I/O Device Emulation, scientists achieved x86 virtualization in the late 1990s, and the company named VMWare was founded in 1998.

Nonetheless, performance stayed a issue for many years, and many administrators did not want server virtualization for some specific workloads and especially for SQL. That's why virtualizing SQL Server was once unheard of, and it's still refused by old style DBAs.

Here's where SLAT comes in. And it will make your DBAs change their mind.

SECOND LEVEL ADDRESS TRANSLATION
 
SLAT is a mechanism that enables the CPU to keep the mapping between the VM virtual memory (known as Guest Virtual Address, or GVA), the VM physical memory (aka GPA, or Guest Physical Address) and the physical memory in the virtualization host (aka System Physical Address, or SPA).
 
So, since the translation is done in the processor, the hypervisor processing overhead is significantly reduced.

There are many virtualization gurus out there explaining the ins and outs of SLAT as well as the advantages of this technology over older memory translation mechanisms. The important concept to grasp is that the goal of the Secondary Level Address Translation is to increase performance of your virtual machines by adding a new improved memory management capability inside the processors.

The third requirement of Popek and Goldberg is fulfilled. Virtual machines have finally become efficient and Microsoft is forcing us to take advantage of the most recent technology achievements by making SLAT mandatory.

HOW TO CHECK FOR SLAT
 
Now, which is the way to check for SLAT support on your computer? Powershell is one of the answers. There are others of course, like the small but powerful utility named Coreinfo (by Mark Russinovich), which if used in conjunction with the -v parameter dumps virtualization-related features including support for second level address translation.

Coreinfo must be launched with admin rights on Intel platforms otherwise you'll get the following message:

.\Coreinfo.exe -v

Coreinfo v3.31 - Dump information on system CPU and memory topology
Copyright (C) 2008-2014 Mark Russinovich
Sysinternals - www.sysinternals.com

Intel(R) Core(TM)2 Duo CPU     T7500  @ 2.20GHz
Intel64 Family 6 Model 15 Stepping 11, GenuineIntel
Microcode signature: 000000BA

Administrator rights are required to query Intel virtualization support.
So, right-click your Powershell icon, Run as administrator and get the desired information:

.\Coreinfo.exe -v

Coreinfo v3.31 - Dump information on system CPU and memory topology
Copyright (C) 2008-2014 Mark Russinovich
Sysinternals - www.sysinternals.com

Intel(R) Core(TM)2 Duo CPU     T7500  @ 2.20GHz
Intel64 Family 6 Model 15 Stepping 11, GenuineIntel
Microcode signature: 000000BA
HYPERVISOR      -       Hypervisor is present
VMX             *       Supports Intel hardware-assisted virtualization
EPT             -       Supports Intel extended page tables (SLAT)
In my case the laptop I am using has support for VMX, as indicated by the '*' in the output, but doesn't support EPT (which is the Intel acronym for SLAT), as indicated by the '-' in the output.
 
If I run the same tiny utility on a more recent processor I get a positive answer:

.\Coreinfo.exe -v

Coreinfo v3.31 - Dump information on system CPU and memory topology
Copyright (C) 2008-2014 Mark Russinovich
Sysinternals - www.sysinternals.com

Intel(R) Celeron(R) CPU G530 @ 2.40GHz
Intel64 Family 6 Model 42 Stepping 7, GenuineIntel
Microcode signature: 00000028
HYPERVISOR      -       Hypervisor is present
VMX             *       Supports Intel hardware-assisted virtualization
EPT             *       Supports Intel extended page tables (SLAT)

ENTER POWERSHELL

But why lose time installing legacy exes when you have Powershell? With Powershell you can easily check for this SLAT information:

(Get-CimInstance Win32_Processor) | Format-List Name,SecondLevelAddressTranslationExtensions


Name                                    : Intel(R) Celeron(R) CPU G530 @ 2.40GHz
SecondLevelAddressTranslationExtensions : True
Just remember that the SecondLevelAddressTranslationExtensions property is supported starting from Windows 8/2012, so the cmdlet won't work on older versions of Windows.

Other virtualization-related properties you should check when thinking of implementing Hyper-V on your laptop are:
  • VirtualizationFirmwareEnabled
  • VMMonitorModeExtensions
  • DataExecutionPrevention
MAKING A TOOL

The whole requirement check could be consolidated in a simple re-usable function:

function Check-HyperV{

    <#

    .SYNOPSIS

    Checks Hyper-V requirements

    .DESCRIPTION

    This check processor compatibility with Hyper-V

    .PARAMETER ComputerName

    A computer name.

    .EXAMPLE

    Check-HyperV -ComputerName server01

    #> 

    [CmdletBinding()]

    param(

        [Parameter(Mandatory=$True,ValueFromPipeline=$True)][string[]]$ComputerName,

        [switch]$detailed

        )

        foreach($computer in $computername){

            try{

                $ComputerInfo = Get-CimInstance Win32_Computersystem -ComputerName $computer

                $ProcInfo = Get-CimInstance Win32_Processor -ComputerName $computer

                $OsInfo = Get-CimInstance Win32_Operatingsystem -ComputerName $computer

                $VirtualizationInfo = [ordered]@{

               OSArchitecture = $OsInfo.OSArchitecture

               TotalPhysicalMemory=[math]::Round($ComputerInfo.TotalPhysicalMemory/1gb)

               SLAT = $ProcInfo.SecondLevelAddressTranslationExtensions;

               VirtualizationFirmwareEnabled = $ProcInfo.VirtualizationFirmwareEnabled;

               VMMonitorModeExtensions = $ProcInfo.VMMonitorModeExtensions;

               DEP= $OsInfo.DataExecutionPrevention_available

               }

                }

            catch{

                Write-Warning "$computer failed!"

                $ErrorHappened = $True

                }

            if(!$ErrorHappened){

                if($detailed)

                    {

                    $VirtualizationInfo

                    }

                " "

                if(

                    ($VirtualizationInfo.OSArchitecture -eq '64-bit') -and

                    ($VirtualizationInfo.TotalPhysicalMemory -ge 4) -and

                    ($VirtualizationInfo.SLAT) -and

                    ($VirtualizationInfo.VirtualizationFirmwareEnabled) -and

                    ($VirtualizationInfo.VMMonitorModeExtensions) -and

                    ($VirtualizationInfo.DEP)

                  )

                    {"Hyper-V requirements filled on  $Computer!"}

                else

                    {"Time to replace $Computer..."}

                ""

                }

     }

}

Check-HyperV srv01,srv02 -detailed
I hope you have enjoyed this blog post and learned some Powershell as well as some important pieces of the history of IT, which is so easily forgotten. Do not hesitate to comment on the subject as well to correct me if I am wrong or unclear.

Be kind, share!

UPDATE 27 nov 2015

There is an additional method to check for Hyper-V requirements, based on both systeminfo and PowerShell: 
systeminfo | select -last 4
Hyper-V Requirements:      VM Monitor Mode Extensions: Yes
                           Virtualization Enabled In Firmware: No
                           Second Level Address Translation: Yes
                           Data Execution Prevention Available: Yes

Monday, May 25, 2015

Moving from ping, netstat and ipconfig to Powershell

Ping, Netstat and Ipconfig are the three major legacy commands that every Windows system administrator out there has been using for decades and that, I bet, most of you are still using pretty often notwithstanding the large spread of Powershell. Well, I am not telling you to switch to Powershell today for performing basic tasks like pinging hosts or clearing your DNS cache. I am just going to show you the cmdlets that in Powershell do these tasks. And, knowing the fact that Powershell is an object-based language with a strong pipeline support, you imagine that using the Powershell way is a better option and gives you a flexible syntax as wel as re-usable results.

PING

Let's start from the first legacy command. While working in a research laboratory, back in 1983, in just one evening, Mike Muuss wrote the ancestor of the small utility that everyone of us knows as being the first tool to use to check network connectivity: ping.exe.

Microsoft came up a great amount of years later with a new cmdlet that leverages ICMP for its second version of Powershell: Test-Connection.

Test-Connection is based on the Win32_PingStatus class and since Powershell 3.0 supports a -Source parameter, which makes the use of this cmdlet particularly interesting over the use of old style pings. In fact, the -Source parameter allows you to specify the names of the computer where the ping originates from:

Test-Connection -Source Src01, Src02, Src03 -ComputerName Dst01
Also, Test-Connection allows you to ping multiple hosts at once:

Test-Connection -ComputerName Dst01, Dst02, Dst03
Using Test-Connection instead of ping allows you to take advantage of the $? variable to perform conditional actions:

if(Test-Connection nonexistingserver){'succeded'}else{'Failed'}
Test-Connection : Testing connection to computer 'nonexistingserver' failed: No such host is known
At line:1 char:4
+ if(Test-Connection nonexistingserver){'succeded'}else{'Failed'}
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : ResourceUnavailable: (nonexistingserver:String) [Test-Connection], PingException
+ FullyQualifiedErrorId : TestConnectionException,Microsoft.PowerShell.Commands.TestConnectionCommand
if(Test-Connection -ComputerName Server01 -Quiet){New-PSSession Server01}
This variable is not available for legacy commands (as I explained in this previous post), so the value of $? stays $True when you use legacy ping, and this is a limiting factor in using ping.exe in conditional statements:

if(ping nonexistingserver){'succeded'}else{'Failed'}
succeded
So now, if you are decided to replace the ping command with Test-Connection, you can simply create an alias named 'Ping' and you're set:

Set-Alias ping Test-Connection
or if you want a quicker way, just name the alias 'p':

Set-Alias p Test-Connection
IPCONFIG

The second command I want to talk of is ipconfig, which is the command used primarly to output your computer network configuration. This command was introduced 20 years ago, in 1995-1996, to Windows 95, at a time when putting the IP stack on everyone's PC was the main task of administrators and this involved typing arcane IPv4 numbers into the now forgotten winipcfg, which was in turn created for Windows 3.1 years before (remember the Wolverine stack?).

Ipconfig has four major switches as old as dinosaurs: /all, /flushdns, /displaydns and /registerdns. All of them have corresponding Powershell cmdlets, which I must admit makes them hard to remember. In any case working with network adapters has taken a great swing starting with Windows 8 and Windows 2012, when a new wave of network-oriented cmdlets belonging to the NetTCPIP module has appeared along with the underlying CIM namespaces and classes.

Ipconfig /all can be replaced by Get-NetIPConfiguration. Tough their output is more or less the same, a few consideration can be made about the improvement the Powershell cmdlet has brought to its predecessor. First of all, Get-NetIPConfiguration has switches for querying remote hosts: -Computername and -Cimsession.

You could for instance create a CIM session to pass to Get-NetIPConfiguration, even do for the moment the -CimSession switch of this cmdlet does not accept an array of computers:

$cimsession = New-CIMsession -Computername srv01

Get-NetIPConfiguration -CimSession $cimsession
Now, since Get-NetIPConfiguration returns an object, you could retrieve just one or more properties:

$ipconf = Get-NetIPConfiguration
$ipconf.DNSServer

InterfaceAlias               Interface Address ServerAddresses
                             Index     Family
--------------               --------- ------- ---------------
Wi-Fi                                4 IPv6    {}
Wi-Fi                                4 IPv4    {192.168.1.1, 192.168.1.1}
Bluetooth Network Connection         8 IPv6    {fec0:0:0:ffff::1, fec0:0:0:ffff:...
Bluetooth Network Connection         8 IPv4    {}
Ethernet                             3 IPv6    {}
Ethernet                             3 IPv4    {192.168.1.254}
Powerful, isn't it?

Now, for the lazy admin, know that the NetTCPIP module exports an alias for Get-NetIPConfiguration: gip. And since gip is way shorter than ipconfig, you have no reasons left to stick with the old command.

Ipconfig /flushdns can be replaced by Clear-DnsClientCache. This cmdlet purges the cache the client-side DNS cache that Windows stores on your computers.

The equivalent of Ipconfig /RegisterDns is Register-DnsClient. As its predecessor, Register-DnsClient invokes un update of the DNS names on all the interfaces of your computer.

NETSTAT

The last command I'd like to talk about today is the old glorious netstat. I am a huge fan of this command since it saved me in many cases when working on network connectivity issues with firewalls and application ports. Nonetheless the time has arrived to explore the Powershell way of implementing the same functions.

Netstat -a, which is used to display connections and listening ports, has evolved toward Get-NetTCPConnection since Windows 2012 and Windows 8. The output is an object with six default fields:

Get-NetTCPConnection

LocalAddress                        LocalPort RemoteAddress                       RemotePort State       AppliedSetting
------------                        --------- -------------                       ---------- -----       --------------
::                                  49157     ::                                  0          Listen
::                                  49156     ::                                  0          Listen
::                                  49155     ::                                  0          Listen
::                                  49154     ::                                  0          Listen
::                                  49153     ::                                  0          Listen
::                                  49152     ::                                  0          Listen
::                                  445       ::                                  0          Listen
::                                  135       ::                                  0          Listen
192.168.1.32                        49465     204.79.197.213                      443        Established Internet
0.0.0.0                             49157     0.0.0.0                             0          Listen
0.0.0.0                             49156     0.0.0.0                             0          Listen
0.0.0.0                             49155     0.0.0.0                             0          Listen
0.0.0.0                             49154     0.0.0.0                             0          Listen
0.0.0.0                             49153     0.0.0.0                             0          Listen
0.0.0.0                             49152     0.0.0.0                             0          Listen
0.0.0.0                             135       0.0.0.0                             0          Listen
The greatest strength of Get-NetTCPConnection over netstat is the possibility to filter on connection state on the fly:

Get-NetTCPConnection -State Established

LocalAddress     LocalPort RemoteAddress        RemotePort State       AppliedSetting
------------     --------- -------------        ---------- -----       --------------
192.168.1.32     49465     204.79.197.213       443        Established Internet
This means that you can easily filter down all connections which are in the state SYN_SENT, that is connections that are being blocked by a security firewall:

Get-NetTCPConnection -State SynSent
Get-NetTCPConnection : No MSFT_NetTCPConnection objects found with property 'State' equal to 'SynSent'.  Verify the
value of the property and retry.
At line:1 char:1
+ Get-NetTCPConnection -State SynSent
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (SynSent:State) [Get-NetTCPConnection], CimJobException
    + FullyQualifiedErrorId : CmdletizationQuery_NotFound_State,Get-NetTCPConnection
In the previous example, no connection is being blocked, so the big red error shown must be interpreted as a good news. Irony of IT.

For completeness, the possible connection states accepted by Get-NetTCPConnection are: Closed, Listen, SynSent, SynReceived, Established, FinWait1, FinWait2, CloseWait, Closing, LastAck, TimeWait and DeleteTCB.

There is another truly important switch for netstat that we are going to discuss to complete this blog post: -r. Using netstat with -r prints the routing table of your computer. The output you get is historically the same that you can get by using 'route print':

route print
===========================================================================
Interface List
  8...e4 d5 3d fd 15 99 ......Bluetooth Device (Personal Area Network)
  4...64 27 37 32 22 d1 ......Broadcom 4313GN 802.11b/g/n 1x1 Wi-Fi Adapter
  3...ec 9a 74 56 e8 89 ......Realtek PCIe GBE Family Controller
  1...........................Software Loopback Interface 1
  6...00 00 00 00 00 00 00 e0 Teredo Tunneling Pseudo-Interface
===========================================================================

IPv4 Route Table
===========================================================================
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    306
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    306
  127.255.255.255  255.255.255.255         On-link         127.0.0.1    306
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    306
  255.255.255.255  255.255.255.255         On-link         127.0.0.1    306
===========================================================================
Persistent Routes:
  None

IPv6 Route Table
===========================================================================
Active Routes:
 If Metric Network Destination      Gateway
  1    306 ::1/128                  On-link
  1    306 ff00::/8                 On-link
===========================================================================
Persistent Routes:
  None
In Powershell the cmdlet to use to get this piece of information is Get-NetRoute. In the case of Get-NetRoute, the interesting feature to highlight is of course the possibility to sort routes by metric:

Get-NetRoute | Sort-Object RouteMetric

ifIndex DestinationPrefix             NextHop     RouteMetric  PolicyStore
------- -----------------             -------     -----------  -----------
4       0.0.0.0/0                     192.168.1.1 0     ActiveStore
8       fe80::c5ee:f21f:1980:6b41/128 ::          256   ActiveStore
4       fe80::a820:ec8e:e0c5:b536/128 ::          256   ActiveStore
3       fe80::44ad:3bde:8351:1b7/128  ::          256   ActiveStore
1       ff00::/8                      ::          256   ActiveStore
4       ff00::/8                      ::          256   ActiveStore
8       ff00::/8                      ::          256   ActiveStore
3       ff00::/8                      ::          256   ActiveStore
6       2001::/32                     ::          256   ActiveStore
3       fe80::/64                     ::          256   ActiveStore
6       ::/0                          ::          256   ActiveStore
1       ::1/128                       ::          256   ActiveStore
6       fe80::/64                     ::          256   ActiveStore
6       fe80::ffff:ffff:fffe/128      ::          256   ActiveStore
8       fe80::/64                     ::          256   ActiveStore
4       fe80::/64                     ::          256   ActiveStore
4       224.0.0.0/4                   0.0.0.0     256   ActiveStore
8       224.0.0.0/4                   0.0.0.0     256   ActiveStore
3       224.0.0.0/4                   0.0.0.0     256   ActiveStore
1       255.255.255.255/32            0.0.0.0     256   ActiveStore
4       255.255.255.255/32            0.0.0.0     256   ActiveStore
8       255.255.255.255/32            0.0.0.0     256   ActiveStore
3       255.255.255.255/32            0.0.0.0     256   ActiveStore
1       224.0.0.0/4                   0.0.0.0     256   ActiveStore
1       127.0.0.1/32                  0.0.0.0     256   ActiveStore
1       127.0.0.0/8                   0.0.0.0     256   ActiveStore
6       ff00::/8                      ::          256   ActiveStore
1       127.255.255.255/32            0.0.0.0     256   ActiveStore
4       192.168.1.255/32              0.0.0.0     256   ActiveStore
4       192.168.1.32/32               0.0.0.0     256   ActiveStore
4       192.168.1.0/24                0.0.0.0     256    ActiveStore
I hope you learned something. It's time to reimagine ipconfig, ping and netstat, guys. Time to move to Powershell and become a faster, more powerful admin. A zillion of cmdlets (network-oriented or not) are waiting for you.

The pipeline is yours.

Friday, May 22, 2015

Powershell and exit status for cmdlets and commands

In Unix and Linux systems you can use the $? variable to find out the exit status of a command. To make a long story short, when you type commands in a UNIX shell, $? always expands to the status of the most recently executed foreground command or pipeline.

Now, since the original Powershell is based on the POSIX standard (back in the eighties, guys!), which tries to standardize commands from the UNIX Korn Shell, it's somewhat natural that Powershell borrowed this $? variable from its predecessor.

Let me give a few basic tips on the use of it.

The $? is a boolean variable documented in about_Automatic_Variables, and can by design hold only two values: $True or $False.

Get-ChildItem C:\Windows\System32\drivers\etc

    Directory: C:\Windows\System32\drivers\etc

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        10/06/2009     23:00        824 hosts
-a---        10/06/2009     23:00       3683 lmhosts.sam
-a---        10/06/2009     23:00        407 networks
-a---        10/06/2009     23:00       1358 protocol
-a---        10/06/2009     23:00      17463 services

$?
True
Test-Connection nohost -Count 1
Test-Connection : Testing connection to computer 'nohost' failed: The requested name is valid, but no data of the
requested type was found
At line:1 char:1
+ Test-Connection nohost -Count 1
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (nohost:String) [Test-Connection], PingException
    + FullyQualifiedErrorId : TestConnectionException,Microsoft.PowerShell.Commands.TestConnectionCommand

$?
False
Here's how to check the variable type:

$?.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Boolean                                  System.ValueType
So, while in UNIX $? returned 0 or 1, in Powershell it returns $True or $False.

There is another important variable named $LastExitCode which returns the exit command of the last Windows command run:

cmd /C exit 0

$LASTEXITCODE
0
Remember though, $LastExitCode doesn't work with Powershell commands. For instance if we check the value of the variable after a failed Powershell cmdlet, its value stays 0, which means succesful:

Test-Connection nohost -Count 1

Test-Connection : Testing connection to computer 'nohost' failed: The requested name is valid, but no data of the
requested type was found
At line:1 char:1
+ Test-Connection nohost -Count 1
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (nohost:String) [Test-Connection], PingException
    + FullyQualifiedErrorId : TestConnectionException,Microsoft.PowerShell.Commands.TestConnectionCommand

$LASTEXITCODE
0
On the other side, when we check it after a failing legacy or external command, it becomes effective:
ping nohost

Ping request could not find host nohost. Please check the name and try again.

$LASTEXITCODE
1
Also, $LastExitCode isn't populated until you execute a Powershell task that returns an exit code. If you open a fresh Powershell console and search for $LastExitCode... you won't find it:

$LASTEXITCODE -eq $null

True
Nor you will find if you run a Powershell cmdlet:

gci c:\nonexistingfolder

gci : Cannot find path 'C:\nonexistingfolde
At line:1 char:1
+ gci c:\nonexistingfolder
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFoun
    + FullyQualifiedErrorId : PathNotFound,

$LASTEXITCODE -eq $null
True
The variable gets populated only when you run an external executable that returns an exit code, like the ping command:

ping nohost

Ping request could not find host nohost. Please check the name and try again.

$LASTEXITCODE -eq $null
False
I hope this brief description of the the two $? and $LASTEXITCODE variable was clear enough. If you have any specific question do not hesitate to leave it in a comment.

If you liked ths quick post, be kind, share. Alot more to come.
Related Posts Plugin for WordPress, Blogger...