A Little Bit About cfgadm(1M)

OpenSolaris is online. If you're looking to run, build, hack on, peruse, or discuss it, you should be able to find everything you need at opensolaris.org.

If you happened to be taking a look at the commands in usr/src/cmd, you might notice "cfgadm - configuration administration." cfgadm is a command line interface through which dynamically reconfigurable hardware is manipulated on Solaris and now OpenSolaris. Dynamically reconfigurable hardware? That's fancy talk for things like hot pluggable PCI slots, hot swappable SCSI disks, USB slots, and on the midrange and high end SPARC servers, memory, CPUs, I/O devices, and entire system boards. A plugin architecture is used to handle different types of hardware. In usr/src/lib/cfgadm_plugins you can find the plugin directories which include scsi, usb, and pci. These contain directories such as i386, amd64, sparc, and sparcv9 which indicate a version of the plugin is built for the named architecture. For example, the USB plugin is built for all of those, but the sbd (system board) plugin is only built for sparc and sparcv9. That's 32-bit and 64-bit SPARC respectively. Currently, cfgadm is compiled as a 32-bit application, therefore it will just be using the 32-bit plugins.

cfgadm's interface is based on an abstraction centered around attachment points. A reconfigurable hardware device is displayed as an attachment point with a receptacle and occupant. All the work required to display the status of or manipulate an attachment point is handled by a plugin. Running cfgadm as root without any options will list all the attachment points. Check out the cfgadm(1M) man page for all the command line options. Plugins also have man pages, for example, cfgadm_scsi(1M). In the plugin man pages, you should find documentation on how to pass plugin specific options to cfgadm.

At home, I've got an old old 300MHz x86 Celeron box which is running Solaris 10. Running cfgadm as root on this box yields

root@x86solaris #cfgadm
Ap_Id                Type         Receptacle   Occupant     Condition
usb0/1               unknown      empty        unconfigured ok
usb0/2               unknown      empty        unconfigured ok

The cfgadm_usb(1M) man page explains that this means the computer has one USB controller with two ports--neither of which have anything plugged into them. The two ports have Ap_Id's (attachment point identifiers) usb0/1 and usb0/2.

After plugging in a USB mouse:

root@x86solaris #cfgadm
Ap_Id                Type         Receptacle   Occupant     Condition
usb0/1               usb-mouse    connected    configured   ok
usb0/2               unknown      empty        unconfigured ok

After plugging in my monitor/USB hub with keyboard and mouse attached:

root@x86solaris #cfgadm
Ap_Id                Type         Receptacle   Occupant     Condition
usb0/1               usb-hub      connected    configured   ok
usb0/1.1             usb-hub      connected    configured   ok
usb0/1.1.1           usb-mouse    connected    configured   ok
usb0/1.1.2           unknown      empty        unconfigured ok
usb0/1.1.3           usb-device   connected    configured   ok
usb0/1.2             unknown      empty        unconfigured ok
usb0/1.3             unknown      empty        unconfigured ok
usb0/1.4             unknown      empty        unconfigured ok
usb0/2               unknown      empty        unconfigured ok

OK, you get the idea. So how does it work? If you run ldd on cfgadm, you'll see it makes use of libcfgadm (libcfgadm(3LIB)) and libdevinfo (libdevinfo(3LIB).)

root@x86solaris #ldd /usr/sbin/cfgadm 
libcfgadm.so.1 =>    /usr/lib/libcfgadm.so.1
libc.so.1 =>         /lib/libc.so.1
libdevinfo.so.1 =>   /lib/libdevinfo.so.1
libnvpair.so.1 =>    /lib/libnvpair.so.1
libnsl.so.1 =>       /lib/libnsl.so.1
libmp.so.2 =>        /lib/libmp.so.2
libmd5.so.1 =>       /lib/libmd5.so.1
libscf.so.1 =>       /lib/libscf.so.1
libdoor.so.1 =>      /lib/libdoor.so.1
libuutil.so.1 =>     /lib/libuutil.so.1
libm.so.2 =>         /lib/libm.so.2

To list all the attachment points on the system, cfgadm calls into libcfgadm, then libcfgadm uses libdevinfo to get a snapshot of the device tree. It then walks the device tree and attempts to find a suitable plugin for each device node in the tree. If a suitable plugin is found, the plugin is used to get the status of the attachment point. This happens in the list_common() routine inside libcfgadm. di_init(3DEVINFO) is used to get the device tree snapshot and di_walk_minor(3DEVINFO) is used to walk the tree, calling the supplied routine do_list_common() on each minor node. Then, once control is handed off to the plugin, it can call into the kernel and talk to the driver.

I've fixed some bugs in the sbd cfgadm plugin so I'll give an example of how that plugin works. First, here's the output from cfgadm on a domain on one of our high end SPARC systems.

# cfgadm
Ap_Id                Type         Receptacle   Occupant     Condition
IO5                  HPCI         connected    configured   ok
IO5_C3V0             pci-pci/hp   connected    configured   ok
IO5_C3V1             unknown      connected    unconfigured unknown
IO5_C5V0             pci-pci/hp   connected    configured   ok
IO5_C5V1             pci-pci/hp   connected    configured   ok
SB5                  V3CPU        connected    configured   ok
SB6                  V3CPU        connected    configured   ok
c0                   scsi-bus     connected    configured   unknown
c1                   scsi-bus     connected    configured   unknown
c2                   scsi-bus     connected    unconfigured unknown
c3                   scsi-bus     connected    unconfigured unknown

# cfgadm -a SB6
Ap_Id                Type         Receptacle   Occupant     Condition
SB6                  V3CPU        connected    configured   ok
SB6::cpu0            cpu          connected    configured   ok
SB6::cpu1            cpu          connected    configured   ok
SB6::cpu2            cpu          connected    configured   ok
SB6::cpu3            cpu          connected    configured   ok
SB6::memory          memory       connected    configured   ok

The SB5, SB6, and IO5 attachment points represent system boards which are handled by the sbd plugin. Without getting into too much detail about domains and system boards, running "cfgadm -c disconnect SB6" on this system will start Solaris off on a quest to remove board SB6 from the system bus. This capability is a large part of Solaris' Dynamic Reconfiguration (DR) feature. The sbd plugin is going to schedule a sequence of operations required to transition the board board from being configured and in use by Solaris, to having the board (and all its resident CPUs and memory) be completely isolated from Solaris and ready to be powered down. The plugin uses an ordered list of commands, which are defined in ap.h. The function ap_seq_get() looks at the current status of the board and determines the first and last command that should be executed in sequence from the list. ap_seq_exec() is where the plugin iterates through the command list and for many of the commands, such as CMD_DISCONNECT, ap_ioctl() is called. So this is where the plugin calls into the kernel, letting the DR driver handle the work required to get Solaris off the CPUs and memory being disconnected.

Technorati Tag:
Technorati Tag:


Thanks for your eludication of this command whose usefulness I am only now discovering.

Posted by Larry Sherwood on June 25, 2005 at 08:18 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed

It's a blog.


Top Tags
« July 2016