Libtune API documentation

Version 0.1
2005/09/22

Nadia Derbey
Nadia.Derbey@bull.net



1. Overview
2. Supported kernels and distros
3. The libtune API interfaces
    3.1. Getting information (tun_get)
        3.1.1. Description
        3.1.2. Parameters
        3.1.3. Returned values
    3.2. Setting information (tun_set)
        3.2.1. Description
        3.2.2. Parameters
        3.2.3. Returned values
    3.3. Locating information (tun_locate)
        3.3.1. Description
        3.3.2. Parameters
        3.3.3. Returned values
    3.4. Getting the key word for a location (tun_get_kwd)
        3.4.1. Description
        3.4.2. Parameters
        3.4.3. Returned values
    3.5. Getting all the valid keywords (tun_lst_all)
         3.5.1. Description
         3.5.2. Parameters
         3.5.3. Returned values
    3.6. Getting help information (tun_help)
         3.6.1. Description
         3.6.2 Parameters
         3.6.3. Returned values
4. Supported tunables
    4.1. Red Hat specific tunables
    4.2. SuSE specific tunables
5. Howto
    5.1. How to add support for a new kernel release
         5.1.1. Include files
         5.1.2. C source files
    5.2. How to add support for a new distribution
    5.3. How to add support for a new family within an existing distribution
         5.3.1. Include files
         5.3.2. C source files
    5.4. How to add support for a new tunable
         5.4.1. Kernel specific tunable
         5.4.2. Distro-dependent tunable
End of document




1. Overview

Accessing kernel tunables, system information and resource consumptions is needed during the whole life cycle of an application, starting from its installation. This access is usually implemented through installation and supervision scripts. Unfortunately, the following issues have been identified:
  1. These scripts are rarely portable. since they require to get, set and change values that are represented by objects that may change from distribution to distribution, or even from one release to the other inside the same distribution.
  2. There are quite multiple ways of accessing the kernel configuration and tunables: procfs, sysfs, existing syscalls or library routines, etc...
This raises the need for a standard, well defined API to manipulate the kernel configuration and tunables for software products to relay on.

The goal of the libtune API is to unify the various ways Linux developers have to access kernel tunables, system information, resource consumptions. The libtune API is built on top of the existing mechanisms, instead of replacing them, in order to maintain backward compatibility.

In the following chapters, we first present the supported kernel and distros supported today. Then, the API interfaces are  presented. Follows a chapter about the tunables that are supported today. Finally, a howto is given: how to add support for a new kernel, how to add support for a new distro, how to add support for a new tunable.

2. Supported kernels and distros

kernel

Distributions
Novell
Red Hat
Family
Family release
Family
Family release
2.6.5
SLES (SuSE Linux Enterprise Server)
9
FC (Fedora Core)
2
2.6.9


FC (Fedora Core)
3


RHEL (Red Hat Enterprise Linux)
4
2.6.11
(Open) SuSE
9.3
FC (Fedora Core)
4


3. The libtune API interfaces

3.1. Getting information (tun_get)

#include <libtune.h>
size_t tun_get(int
keyword, void *identifier, char **out_buff, size_t *out_sz)

3.1.1. Description

This routine is used to get a tunable value: given a keyword that uniquely identifies a tunable, it returns its value (as read from the underlying /proc or /sys file). See next chapters to have a list of the supported tunables.
The value is returned as a buffer of characters (out_buff), whose size is out_sz.
For the tunables that depend on an identifier (pid, CPU id, etc), that identifier can be provided through the identifier parameter.

3.1.2. Parameters

This routine takes the following parameters:

3.1.3. Returned values

On  success,  tun_get() returns the number of characters read, including the terminating null character, but not including the EOF character. This value can be used to handle embedded null characters in the data read.
tun_get() returns -1 on failure, and errno is set:

EINVAL
keyword is invalid

identifier is a NULL pointer, while the tunable asked for needs an identifier

identifier is an empty string, while the tunable asked for needs an identifier

outbuf is a NULL pointer

out_sz is a NULL pointer
ENODATA
The value looked for could not be found
ESRCH
identifier points to an invalid pid
EPERM
the calling application does not have the neccessary rights to get the needed tunable value
ENOENT
the underlying file does not exist.
ENOMEM
if the API failed to allocate memory

3.2. Setting information (tun_set)

#include <libtune.h>
size_t tun_set(int
keyword, void *identifier, char *in_buff, size_t in_sz, char **out_buff, size_t *out_sz)

3.2.1. Description

This routine is used to set a tunable value: given a keyword that uniquely identifies a tunable, it sets its value to the string contained in in_buff, whose size is in_sz (by writing that value into the underlying /proc or /sys file). See next chapters to have a list of the supported tunables.
The previous tunable value is returned as a buffer of characters (out_buff), whose size is out_sz.
For the tunables that depend on an identifier (pid, CPU id, etc), that identifier can be provided through the identifier parameter.

3.2.2. Parameters

This routine takes the following parameters:

3.2.3. Returned values

On  success,  tun_set() returns the number of output characters, including the terminating null character, but not including the EOF character. This value can be used to handle embedded null characters in the data read.
tun_set() returns -1 on failure, and errno is set:
EINVAL
keyword is invalid

identifier is a NULL pointer, while the tunable asked for needs an identifier

identifier is an empty string, while the tunable asked for needs an identifier

in_buff is a NULL pointer

in_sz has a 0 value

outbuf is a NULL pointer

out_sz is a NULL pointer

keyword is one of TUN_H_OP_MAX, TUN_S_OP_MAX, TUN_H_CHILD_MAX, TUN_S_CHILD_MAX, TUN_S_STK_MAX, TUN_S_DATA_MAX, TUN_S_VM_MAX and the input buffer is not a string of digits
ESRCH
identifier points to an invalid pid
EPERM
the calling application does not have the neccessary rights to set the needed tunable value
ENOENT
the underlying file does not exist.
ENOMEM
if the API failed to allocate memory
ERANGE
keyword is one of TUN_H_OP_MAX, TUN_S_OP_MAX, TUN_H_CHILD_MAX, TUN_S_CHILD_MAX, TUN_S_STK_MAX, TUN_S_DATA_MAX, TUN_S_VM_MAX and the input buffer contains a value that is out of range

3.3. Locating information (tun_locate)

#include <libtune.h>
int tun_locate(int keyword, char **location, int *loc_sz)

3.3.1. Description

This routine can be used to locate the underlying pseudo-file of a tunable: given a keyword, it returns in the string pointed to by location the path to the underlying pseudo-file. The path size is stored into loc_sz.
This routine is only meaningful for indexes that correspond to information that is managed through pseudo files.

3.3.2. Parameters

This routine takes the following parameters:

3.3.3. Returned values


EINVAL
keyword is invalid

outbuf is a NULL pointer

out_sz is a NULL pointer
ENOMEM
if the API failed to allocate memory

3.4. Getting the key word for a location (tun_get_kwd)

#include <libtune.h>
char *
tun_get_kwd(char *location, int *keyword)

3.4.1. Description

This is the reverse operation of the preceding one: given a location, it returns the associated keyword (to use for example in a set / get operation). It also returns a string that gives the corresponding constant name. Actually, since many tunables may have the same location, it is recommended to call this routine several times in order to get back all the possible keywords and constant names that correspond to the same location.
Example of tunables that have the same underlying location:

3.4.2. Parameters

This routine takes the following parameters:

3.4.3. Returned values

If successful, tun_get_kwd() returns a pointer to the next constant name for the specified location (this string is malloc'ed by the library and should then be freed by the calling application), or NULL if the location is not found anymore (in that case, *keyword is not updated and errno is set to ENOENT).
Note: if the location corresponds to a keyword that has been generated by the daemon, an empty string is returned ("").
On failure, ((char *) -1) is returned, *keyword is not updated and errno is set:

EINVAL
location is a NULL pointer

keyword points to an invalid value

location is an empty string

keyword is a NULL pointer
ENOMEM
if the API failed to allocate memory

3.5. Getting all the valid key words (tun_lst_all)

#include <libtune.h>
int tun_lst_all(int *keyword)

3.5.1. Description

This is an interface that can be used to get all the valid tunables present in the TUNDB database: given a keyword, it returns the next valid one in the supported tunables. This interface, combined with tun_help() (see below) is useful to know what are the tunables covered by the libtune API.

3.5.2. Parameters

This routine takes the following parameters:

3.5.3. Returned values

If successful, tun_lst_all() returns 0 and *keyword is filled with the next valid tunable value.
If there ane nomore valid tunables, TUN_ILLEGAL is returned.
On failure, -1 is returned, *keyword is not updated and errno is set:

EINVAL
keyword is a NULL pointer

keyword points to an invalid value

3.6. Getting help information (tun_help)

#include <libtune.h>
int tun_help(int keyword, char **help, size_t *help_sz)

3.6.1. Description

This routine can be used, given a keyword value, to return the corresponding help string into the string pointed to by help. The string size is stored into help_sz.

3.6.2. Parameters

This routine takes the following parameters:

3.6.3. Returned values


EINVAL
keyword is invalid

help is a NULL pointer

help_sz is a NULL pointer
ENOMEM
if the API failed to allocate memory

4. Supported tunables

Constant name
Tunable meaning
id parameter in the API interfaces
location
TUN_SHMMIN Minimum shm segment size (in bytes)


TUN_H_OP_MAX
Max number of open fds (hard limit)

TUN_S_OP_MAX Max number of open fds (soft limit)

TUN_H_CHILD_MAX Max number of processes (hard limit)

TUN_S_CHILD_MAX Max number of processes (soft limit)

TUN_S_STK_MAX stack size (soft limit)

TUN_S_DATA_MAX size of data segment (soft limit)

TUN_S_VM_MAX size of virtual memory (soft limit)

TUN_SEMMSL Max number of semaphores per id
/proc/sys/kernel/sem
TUN_SEMMNS Max number of semaphores in the system
/proc/sys/kernel/sem
TUN_SEMMNI Max number of semaphore identifiers
/proc/sys/kernel/sem
TUN_SEMOPM Max number of operations per semop call
/proc/sys/kernel/sem
TUN_REC_PACKS Number of receive packets for <interface> Network interface (string)
/proc/net/dev
TUN_MEMSPACE
Total memory space

/proc/meminfo
TUN_SWAPTOT Total swap space
/proc/meminfo
TUN_SWAPFREE
Free swap area
/proc/meminfo
TUN_HPGTOT Total number of huge pages
/proc/meminfo
TUN_HPGFREE Number of free huge pages
/proc/meminfo
TUN_HPGSZ Huge page size
/proc/meminfo
TUN_CTX_SW Number of context switches
/proc/stat
TUN_CPUPHYSID Physical id for <cpuid> CPU id (integer)
/proc/cpuinfo
TUN_SIBLINGS Number of sibling CPUs for CPU <cpuid> CPU id (integer)
/proc/cpuinfo
TUN_SHMMNI Maximum number of shm segment ids
/proc/sys/kernel/shmmni
TUN_SEM All semaphore parameters
/proc/sys/kernel/sem
TUN_CMDLINE Complete command line for process <pid> Process id (integer)
/proc/<PID>/cmdline
TUN_STAT Statistics for process <pid> Process id (integer)
/proc/<PID>/stat
TUN_MEMINFO Memory statistics
/proc/meminfo
TUN_SLEEPSTATE Sleep state
/sys/power/state
TUN_CPULIMITS limits for CPU <cpuid> CPU id (integer)
/proc/acpi/processor/CPU<CPUID>/limit
TUN_FILEMAX Max number of files

/proc/sys/fs/file-max
TUN_CPUINFO CPU info
/proc/cpuinfo
TUN_FIN_TIMEOUT Timeout for a FIN packet before the socket is forcibly closed
/proc/sys/net/ipv4/tcp_fin_timeout
TUN_MAX_BACKLOG Maximum # of queued connection requests which have still not received an ACK from the connecting client
/proc/sys/net/ipv4/tcp_max_syn_backlog
TUN_TW_REUSE Allow to reuse TIME-WAIT sockets for new connections
/proc/sys/net/ipv4/tcp_tw_reuse
TUN_LOC_P_RANGE Local port range used by TCP and UDP
/proc/sys/net/ipv4/ip_local_port_range
TUN_IPV4_RMEM Min-default-max memory size of the TCP receive buffers
/proc/sys/net/ipv4/tcp_rmem
TUN_IPV4_WMEM Min-default-max memory size of the TCP send buffers
/proc/sys/net/ipv4/tcp_wmem
TUN_WIN_SCALING Enable TCP to negociate the use of window scaling during connection set up

/proc/sys/net/ipv4/tcp_window_scaling
TUN_MTU_SIZE MTU size for <interface> Network interface (string)
/proc/sys/net/ipv6/conf/<interface>/mtu
TUN_PARTITIONS Disks info
/proc/partitions
TUN_NET_DEV Network device status info
/proc/net/dev
TUN_RMEM_MAX Max receive buffer size
/proc/sys/net/core/rmem_max
TUN_WMEM_MAX Max send buffer size
/proc/sys/net/core/wmem_max
TUN_NET_BACKLOG Max # of received buffers processed before congestion

/proc/sys/net/core/netdev_max_backlog
TUN_OVC_MEM Kernel policy for memory allocation

/proc/sys/vm/overcommit_memory
TUN_OVC_RATIO Percentage of memory added to the swap to get the max address space allowed to be committed

/proc/sys/vm/overcommit_ratio
TUN_SWAPPINESS Swappiness

/proc/sys/vm/swappiness
TUN_NR_HUGE_PG Number of configured huge pages
/proc/sys/vm/nr_hugepages
TUN_P_STAT Kernel and system statistics
/proc/stat

4.1. RedHat specific tunables

Constant name
Tunable meaning
location
FC4 location
TUN_EXEC_SHIELD Security level for the exec-shield functionality - Red Hat specific
/proc/sys/kernel/exec-shield /proc/sys/kernel/exec-shield
TUN_EXEC_SHIELD_R Controls whether to randomize VM mappings - Red Hat specific
/proc/sys/kernel/exec-shield-randomize /proc/sys/kernel/randomize_va_space

4.2. SuSE specific tunables

Constant name
Tunable meaning
id parameter in the API interfaces
location
TUN_MAPPED_BASE Shared memory address map for <pid> - SuSE specific
Process id (integer)
/proc/<PID>/mapped_base

5. Howto

In the following chapters, we explain how to enhance the source tree in order to support more kernel releases, distros, distro families.

5.1. How to add support for a new kernel release

Assume you want to add suport for the 2.6.13 kernel release

5.1.1. Include files

  1. Create the directory include/base-2.6.13
  2. Create the following include files:
  3. Create the distro specific include files (see the Howto's for a new distribution and for a new family).

5.1.2. C source files

  1. Create the directory distro-lib/base-2.6.13
  2. Create the following source files:
    1. distro-lib/base-2.6.13/Makefile. This is the Makefile for the kernel-dependent source files and any distro within this kernel. It can be copied from distro-lib/base-2.6.11/Makefile
    2. distro-lib/base-2.6.13/libtundb_base.c. This is the TUNDB initialization file. It can be copied from distro-lib/base-2.6.11/libtundb_base.c.
    3. distro-lib/base-2.6.13/libtuninit_base.c. This is the TUNLIMITS initialization file. It can be copied from distro-lib/base-2.6.11/libtuninit_base.c.
  3. Create the distro specific source files (see the Howto's for a new distribution and for a new family).

5.2. How to add support for a new distribution

Assume you want to add support for a Red Hat distribution under 2.6.13 kernel release:
  1. Create the directory include/base-2.6.13/distro-REDHAT
  2. Create the directory distro-lib/base-2.6.13/distro-REDHAT
If a distribution other than Red Hat or SuSE is to be supported, scripts/get_distro.sh should be changed to detect that distribution. In that case, the distro-<distro> directory should be created under the appropriate base kernel, <distro> being the result of get_distro.sh -d:
# cd scripts
# DISTRO=`./get_distro.sh -d`
# cd ..
# mkdir include/base-2.6.13/distro-${DISTRO}
# mkdir distro-lib/base-2.6.13/distro-${DISTRO}
Today, the 2 supported values for $DISTRO are REDHAT and SUSE

5.3. How to add support for a new family within an existing distribution

Assume you want to add support for Fedora Core 5 into the Red Hat distribution that is under the 2.6.13 kernel release.
  1. Create the directory include/base-2.6.13/distro-REDHAT/FC/5
  2. Create the directory distro-lib/base-2.6.13/distro-REDHAT/FC/5
If a family other than the ones already supported is to be supported, scripts/get_distro.sh should be changed to detect it. In that case, the <family>/<family_release> directory should be created under the appropriate distribution, <family> being the result of get_distro.sh -f and <family_release> being the result of get_distro.sh -r:
# cd scripts
# D=`./get_distro.sh -d`
# F=`./get_distro.sh -f`
# R=`./get_distro.sh -r`
# cd ..
#
mkdir -p include/base-2.6.13/distro-${D}/${F}/${R}
# mkdir -p distro-lib/base-2.6.13/distro-${D}/${F}/${R}

Today, the values that can be returned by scripts/get_distro.sh for ${R} and ${F} are:

$D
$F
$R
Meaning
REDHAT
FC
1
Fedora Core 1
2
Fedora Core 2
3
Fedora Core 3
4
Fedora Core 4
RH
3.0.3
Red Hat Linux release 3.0.3
4.0
Red Hat Linux release 4.0
4.1
Red Hat Linux release 4.1
4.2
Red Hat Linux release 4.2
5.0
Red Hat Linux release 5.0
5.1
Red Hat Linux release 5.1
5.2
Red Hat Linux release 5.2
6.0
Red Hat Linux release 6.0
6.1
Red Hat Linux release 6.1
6.2
Red Hat Linux release 6.2
7.0
Red Hat Linux release 7.0
7.1
Red Hat Linux release 7.1
7.2
Red Hat Linux release 7.2
7.3
Red Hat Linux release 7.3
8
Red Hat Linux release 8
9
Red Hat Linux release 9
RHEL
2.1
Red Hat Enterprise Linux release 2.1
3
Red Hat Enterprise Linux release 3
4
Red Hat Enterprise Linux release 4
SUSE
SL
any
SuSE Linux
SLES
any
SuSE Linux Enterprise Server

5.3.1. Include files

Create the following include files:

5.3.2. C source files

Create the following source files:
  1. distro-lib/base-2.6.13/distro-REDHAT/FC/5/Makefile. This is the Makefile for the distro-dependent source files. It can be copied from distro-lib/base-2.6.11/distro-REDHAT/FC/4/Makefile
  2. distro-lib/base-2.6.13/distro-REDHAT/FC/5/libtundb_distro.c. This is the TUNDB initialization file. It can be copied from distro-lib/base-2.6.11/distro-REDHAT/FC/4/libtundb_distro.c.
  3. distro-lib/base-2.6.13/distro-REDHAT/FC/5/libtuninit_base.c. This is the TUNLIMITS initialization file. It can be copied from distro-lib/base-2.6.11/distro-REDHAT/FC/4/libtuninit_base.c.

5.4. How to add support for a new tunable

5.4.1. Kernel specific tunable

Assume you want to add the tunable TUN_BLAH_BLAH for the 2.6.13 kernel
  1. define the tunable value into include/base-2.6.13/libtune_base.h, applying the following rule:
    1. if the tunable has no underlying pseudo-file, it should be added in TUNDB_S1: its value should be within [0 - 0x01FF], and contigous to the last defined one
    2. if the tunable has the following properties:
      • an underlying pseudo-file made of a single line, with several fields (ala /proc/sys/kernel/sem)
      • accessing the tunable is done through strat_get_subfile_line() / strat_set_subfile_line(): access a single field within this line
      it should be added in TUNDB_S2: its value should be within [0x0400 - 0x05FF] and contigous to the last defined one in this category.
    3. if the tunable has the following properties:
      • an underlying pseudo-file made of several lines, each line made of several fields and dedicated to one object (ala /proc/net/dev)
      • accessing the tunable is done through strat_get_subfile_lines() / strat_set_subfile_lines(): access a single field within one of these lines
      it should be added in TUNDB_S3: its value should be within [0x0800 - 0x09FF] and contigous to the last defined one in this category.
    4. if the tunable has the following properties:
      • an underlying pseudo-file made of a single block of lines, each line identified by a fixed string (ala /proc/meminfo)
      • accessing the tunable is done through strat_get_subfile_block() / strat_set_subfile_block(): access a single value within one of these lines
      it should be added in TUNDB_S4: its value should be within [0x0C00 - 0x0DFF] and contigous to the last defined one in this category.
    5. if the tunable has the following properties:
      • an underlying pseudo-file made of a several blocks of lines, each line identified by a fixed string, each block of lines dedicated to one object (ala /proc/cpuinfo)
      • accessing the tunable is done through strat_get_subfile_blocks() / strat_set_subfile_blocks(): access a single value within one of these lines inside one of these blocks
      it should be added in TUNDB_S5: its value should be within [0x1000 - 0x11FF] and contigous to the last defined one in this category.
    6. if the tunable has the following properties:
  2. define the following values into include/base-2.6.13/libtune_priv_base.h:
  3. add the tune_t structure for TUN_BLAH_BLAH at the end of the appropriate array (see point 1) into distro-lib/base-2.6.13/libtundb_base.c:
  4. update the l_tunlimits[] array in distro-lib/base-2.6.13/libtuninit_base.c: set tun_idx_last to TUN_BLAH_BLAH for the approriate index (depending on which TUNDB array TUN_BLAH_BLAH has been added to):
    1. impacted array
      Impacted l_tunlimits index
      TUNDB_S1
      S1_LIMITS
      TUNDB_S2 S2_LIMITS
      TUNDB_S3 S3_LIMITS
      TUNDB_S4 S4_LIMITS
      TUNDB_S5 S5_LIMITS
      TUNDB_S6 S6_LIMITS

 5.4.2. Distro-dependent tunable

Assume you want to add the tunable TUN_BLAH_BLAH for the Red Hat Fedora Core 5 distribution
  1. define the tunable value into include/base-2.6.13/distro-REDHAT/FC/5/libtune_distro.h, applying the following rule:
    1. if the tunable has no underlying pseudo-file, it should be added in TUNDB_S1_1: its value should be within [0x0200 - 0x03FF], and contigous to the last defined one
    2. if the tunable has the following properties:
      • an underlying pseudo-file made of a single line, with several fields (ala /proc/sys/kernel/sem)
      • accessing the tunable is done through strat_get_subfile_line() / strat_set_subfile_line(): access a single field within this line
      it should be added in TUNDB_S2_1: its value should be within [0x0600 - 0x07FF] and contigous to the last defined one in this category.
    3. if the tunable has the following properties:
      • an underlying pseudo-file made of several lines, each line made of several fields and dedicated to one object (ala /proc/net/dev)
      • accessing the tunable is done through strat_get_subfile_lines() / strat_set_subfile_lines(): access a single field within one of these lines
      it should be added in TUNDB_S3_1: its value should be within [0x0A00 - 0x0BFF] and contigous to the last defined one in this category.
    4. if the tunable has the following properties:
      • an underlying pseudo-file made of a single block of lines, each line identified by a fixed string (ala /proc/meminfo)
      • accessing the tunable is done through strat_get_subfile_block() / strat_set_subfile_block(): access a single value within one of these lines
      it should be added in TUNDB_S4_!: its value should be within [0x0E00 - 0x0FFF] and contigous to the last defined one in this category.
    5. if the tunable has the following properties:
      • an underlying pseudo-file made of a several blocks of lines, each line identified by a fixed string, each block of lines dedicated to one object (ala /proc/cpuinfo)
      • accessing the tunable is done through strat_get_subfile_blocks() / strat_set_subfile_blocks(): access a single value within one of these lines inside one of these blocks
      it should be added in TUNDB_S5_1: its value should be within [0x1200 - 0x13FF] and contigous to the last defined one in this category.
    6. if the tunable has the following properties:
  2. define the following values into include/base-2.6.13/distro-REDHAT/FC/5/libtune_priv_distro.h:
  3. add the tune_t structure for TUN_BLAH_BLAH at the end of the appropriate array (see point 1) into distro-lib/base-2.6.13/distro-REDHAT/FC/5/libtundb_distro.c (see previous chapter for the rules to apply)
  4. update the d_tunlimits[] array in distro-lib/base-2.6.13/distro-REDHAT/FC/5/libtuninit_distro.c: set tun_idx_last to TUN_BLAH_BLAH for the approriate index (depending on which TUNDB array TUN_BLAH_BLAH has been added to):
    1. impacted array
      Impacted l_tunlimits index
      TUNDB_S1_1
      S1_1_LIMITS
      TUNDB_S2_1 S2_1_LIMITS
      TUNDB_S3_1 S3_1_LIMITS
      TUNDB_S4_1 S4_1_LIMITS
      TUNDB_S5_1 S5_1_LIMITS
      TUNDB_S6_1 S6_1_LIMITS


End of document