Getting the network adapters’ order in Windows

17 Oct

Now, one of the biggest problem for us when deployment new servers is that we want to get everything as automated as possible. One of the most complex to automate is networking configuration. That is, you need to figure out which nic to team and which to set as heartbeat or backup nic, etc. In this, I use nic and network adapter interchangeably.

The most persistent problem is getting a ordered list of network adapters from Windows. Windows itself does not present nics in any order. So your slot 0 (embedded) port 1 could be named as “local area network connection 3” or called “Broadcom 1GB PCI Ethernet Adapter 4” and the slot 10 port 2 nic could be named as the first nic.

We have a standard for deploying servers. The first nic (usually the embedded port 1) is teamed with the first nic card’s port 1 (e.g. slot 2 port 1). Port 2 Embedded is used for backup and the 4th port (in this case, Slot 2 port 2) is used of heartbeat if its a cluster. Now why do we want to do that? The basic idea is that this reduce logistic work for the cabling people and for us also. We all know which port is used for what and don’t have to keep referring to deployment documents when configuring nics (except to get the ip addresses).

If you look into the register, there is a value in HKLM\CurrentControlSet\System\Enum\PCI keys (or the nic’s enum keys) which presents the network adapter with “LocationInformation” with “PCI bus X, device Y, function Z”.

  • The smaller the PCI number. e.g PCI bus 1, the higher the order of the nic, ie. first nic.
  • The smaller the function number within the same PCI bus, the higher the order of the nic, i.e. function 0 could be port 1 and function 1 port 2

Note: I am only talking about network adapters here.

With this information its very easy then to grab this registry value and transform it into some ranking system for the nics. The formula is very easy, multiple PCI number by 10 and add the function number to it (i.e ranking = (10 x pci number) + function number). The smaller the number the higher up in the order.

So all we need to do now is to:

  • use WMI win32_networkadapter to loop through all nics,
  • grab their DeviceID and PNPDevicID (which is the registery key under ENUM, e.g. PCI\VEN_10DE&DEV_07DC&SUBSYS_2A65103C&REV_A2\3&2411E6FE&1&78.
  • Use the PNPDeviceID to look for the LocationInformation value,
  • Create the ranking and sort them and pump them into a dictionary object with the ranking number (I transform those numbers to absolute ranking,e.g. 1, 2,3,etc) and the deviceID.

The final result in the dictionary object should look something like this (where key is the ranking and item is DeviceID of the network adapter):

key     item
==      ===
1        11
2        7
3        12
4        9
5        8

So now all I need is to grab the deviceIDs of order pair nic with ranking 1 and 3 and team them, get the rank 2 and setup the backup IP addresss, etc

Now I created the scripts and got it working on Windows 2003. Then I tried it on Windows 2008 and it failed!

When I looked at the registry value, the LocationInformation is now something like this:

@system32\drivers\pci.sys,#65536;PCI bus %1, device %2, function %3;(3,0,0)

My jaw dropped to think that I finally cracked it and Windows 2008 changed the format. I couldn’t believe my eyes to think that now I cannot easily get PCI and function numbers from registry. I searched the Internet for some answers and all pointed to using some device programming function to retrieve these values.

However, I started to looked a few more of these values, I found something was different in each value. I looked closer and voila! The answer is in the brackets the end of the value! Windows 2008 have moved the PCI, device and function values in a bracket

@system32\drivers\pci.sys,#65536;PCI bus %1, device %2, function %3;(3,0,0)

So in this case, the values are PCI bus 3, device 0, function 0.

Now all I have to do is to change my script logic to grab the values between the brackets instead for Windows 2008 servers.


Posted by on October 17, 2009 in Windows



5 responses to “Getting the network adapters’ order in Windows

  1. Ernie

    January 26, 2010 at 4:06 pm

    Nice take on this problem.
    However, having checked a few of my HP servers, I found that the Broadcom/HP NICs begin with B06BDRV instead of PCI. Not a problem though as its just a different registry path (ENUM\B06BDRV\ instead of ENUM\PCI\).

    Not sure about the reliability of the Bus & Function values though. And what about the device number?
    My on-board NICs are Bus 65, Device 1, Function 0, and Bus 65, Device 2, Funcion 0. Therefore both have the same order number using your formula.
    In addition, the Intel DualPort Adapter on the same server is listed as 8,0,0 and 8,0,1. Therefore the connections on the plug-in adapter would be higher order than the Onboard connections.


    • saltwetfish

      January 26, 2010 at 4:50 pm

      Hi Ernie,

      Thanks for the comments. Yes that is correct, the nics are either present under PCI or it own nic path. I stated that in the 4th paragraph, although it may not be clear to all.

      Unfortunately, my experience is with mainly HP proliant servers, other server and nics may have use DEVICE instead of FUNCTION as you have stated. But this is strange because HP proliant servers do come with broadcom nics and I don’t see the DEVICE part being used.

      If that is that case additional logic will have to added to determine exceptional models where DEVICE is used instead of FUNCTION.

      But I find it strange the the onboard nic would have a bus number that high! We have various models of Proliant and they have always been consistent. What HP models are yours?

  2. Ernie

    February 1, 2010 at 12:09 pm

    Ive now moved onto a DL585-G5. Its got 2 onboard connections and two dual-port PCI Nics.
    After installing the HP Network Config utility (CP011547.exe), I can see from the GUI each network connection is reported as Slot x and Port x. Perfect!
    So for my server…
    Slot 0 Port 1 NC371i (65, 1, 0)
    Slot 0 Port 2 NC371i (65, 2, 0)
    Slot 6 Port 1 NC380T (80, 4, 0)
    Slot 6 Port 2 NC380T (81, 5, 0)
    Slot 7 Port 0 NC380T (3, 4, 0)
    Slot 7 Port 1 NC380T (4, 5, 0)

    As you can see, the exact physical PCI slot is given, with Slot 0 being the integrated NICs. What is strange is the difference in bus numbers reported for the two physical cards, despite being installed side by side in the server.
    All of this information is also available using the HPNetSvy command line utility.

    Ultimately Im trying to determine from within WinPE which “Local Area Connection” relates to which physical port at the back of the server. WMI and the registry dont seem to give me enough information to do this reliably. Ive tried the HPDiscovery.exe tool from the Scripting Toolkit, but again no joy. And the above Network Config Utility doesnt work in Win PE 😦


    • saltwetfish

      February 2, 2010 at 3:41 pm

      Hmmm. I find this rather strange, because my premise also have DL585G5 but I had not encounter such an issue with such a high bus number. Okay, back to your question of relating Windows network name with the physical server. The connectionID and the Index are the 2 key values in both the registry settings and wmi that can help you to determine which adapter is which. In general, all networkadapters have a unique index and NetConnectionID.

      What you need to do is to use the following query:

      Set objWMIService = GetObject(“winmgmts:\\” & SERVERNAME & “\root\CIMV2”)
      Set colNetAdapters = objWMIService.ExecQuery(“Select * from Win32_NetworkAdapter where AdapterTypeID = 0 “)

      And for each ojbnetworkadapter in the colNetAdapters –>
      you look up the registry for “SYSTEM\CurrentControlSet\Enum\” & objNetworkAdapter.PNPDeviceID
      –> this will give you the bus number and device/function numbers you need

      What you then need to do is to associate the objNetworkadapter.index with the bus/slot/port that you got from the registry keys.

      What you then can do is to use this query:

      Set colNetAdapters = objWMIService.ExecQuery(“Select * from Win32_NetworkAdapterConfiguration where Index = ” & strIndex) <— the index association you have above.

      The resultant record's NetConnectionID will be the "local area connection X" that you see in network neighbourhood.

    • Justin O

      April 13, 2010 at 12:42 pm

      Ernie – This is the same problem I’ve struggled with. To this day, I only know of two solutions for obtaining this data programmatically:

      – Parse the HPNetSvy standard output
      – Install the WBEM providers then query HP_WinEthLocation and HP_WinEthernetPort within the root\HPQ namespace. Each of those class provides the properties you’ll need.

      The HP SNMP providers might also be an option but have not been able to find an OID that would give me this data.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: