Intel® Ethernet Controller E810 Application Device Queues (ADQ)

Configuration Guide

ID 609008
Date 04/03/2023
Version 2.8
Document Table of Contents

Set cgroup Priority for Application Network Traffic (If Needed)

Linux Control Groups (cgroups) are used to steer outgoing (Tx) traffic to a set of dedicated hardware queues on the NIC. If egress tc filter(s) were configured in TC Filtering, Linux cgroups are not needed and this step can be skipped. If only ingress tc filter(s) were created, follow the steps in this section to create a cgroup and set the priority of network traffic to align TX packets to the Rx filter queues.

Note:The performance of the two methods (cgroup priority or TC filters with skbedit priority) may differ slightly based on the application or workload.

The following variables are used in the examples this section:

$cgroup_​name The name for the application cgroup.
$app_​pid The process ID for the application.
$iface The network interface that the application uses (PF or VF).
$prio Defines the network priority for the applications belonging to cgroup ${cgroup_​name}.
--sticky An option before the command to keep any child processes in the same cgroup.
$command The task command with arguments to be executed in the cgroup.
  1. Configure cgroup.

    The Network Priority (net_​prio) subsystem of the Control Groups (cgroups) Linux kernel feature provides a way to set the priority of network traffic per each network interface for applications within various cgroups. Typically, an application sets the priority of its traffic via the SO_​PRIORITY socket option. However, if applications are not coded to set the priority value, the administrator can assign a process to a specific cgroup which defines the priority of outgoing traffic on a given network interface.

    Note:Network Priority (net_​prio) using cgroup configuration in this section, or the SO_​PRIORITY socket option in the application, must be configured for symmetric queuing (Configure Symmetric Queues) to work correctly with ADQ. Failure to configure either 1) Network Priority (net_​prio) using cgroups, or 2) SO_​PRIORITY in the application, will result in Tx traffic going to the default TC queues.

    There are two options for cgroup configuration: manually, or through the cgconfig service tools.

    Option 1: Manual cgroup Configuration

    Note:RHEL9.0 does not include the net_​prio module by default. A net_​prio directory must be created under /sys/fs/cgroup/ before mounting it. For example: mkdir /sys/fs/cgroup/net_prio

    This step is not required in RHEL8.X or earlier versions.

    1. Mount the cgroup filesystem. mount -t cgroup -o net_prio none /sys/fs/cgroup/net_prio
    2. Create a new cgroup. mkdir /sys/fs/cgroup/net_prio/${cgroup_name}
    3. Assign the application process to cgroup. echo $app_pid > /sys/fs/cgroup/net_prio/${cgroup_name}/tasks Note:Before running this command, start the server application (for example, redis server, netperf, etc.) and include the specific application PID as $app_​pid.
    4. Set priority to $prio for traffic originating from processes belonging to the net_​prio cgroup. echo "$iface $prio" > /sys/fs/cgroup/net_prio/${cgroup_name}/ \ net_prio.ifpriomap

      Example:

      echo "eth0 1" > /sys/fs/cgroup/net_prio/foo/net_prio.ifpriomap

    Option 2 (Recommended): cgroup Configuration Using CGConfig Service Tools

    1. Make a net_​prio directory and mount it in the /sys/fs/cgroup directory. mkdir /sys/fs/cgroup/net_prio mount -t cgroup -o net_prio none /sys/fs/cgroup/net_prio Note:This step is only applicable for RHEL9.0 and later operating systems because the net_​prio module is not available in the OS repository.
    2. Create a new cgroup. cgcreate -g net_prio:${cgroup_name}
    3. Set the priority for processes belonging to the cgroup.

      The $prio value should map to the position of the targeted TC defined in Create TCs.

      cgset -r net_prio.ifpriomap="$iface $prio" ${cgroup_name}

      Example:

      For example, in the following TC command, map 0 0 1 2 sets priority 0-1 to use TC0, prio 2 to TC1, and prio 3 to TC2.

      ${pathtotc}/tc qdisc add dev $iface root mqprio num_tc 3 map \ 0 0 1 2 queues 2@0 40@2 54@42 hw 1 mode channel cgcreate -g net_prio:app_tc1 cgset -r net_prio.ifpriomap="$iface 2" app_tc1 cgcreate -g net_prio:app_tc2 cgset -r net_prio.ifpriomap="$iface 3" app_tc2
  2. Run the task in the given cgroup (for example, ${cgroup_​name}) cgexec -g net_prio:${cgroup_name} --sticky $command

    Example:

    cgexec -g net_prio:${cgroup_name} --sticky netserver
  3. Verify cgroup configuration:
    1. Verify that the interface is mapped to the right interface: cat /sys/fs/cgroup/net_prio/${cgroup_name}/net_prio.ifpriomap
    2. Show the Process IDs being run in this cgroup and match them to the application Process IDs: cat /sys/fs/cgroup/net_prio/${cgroup_name}/tasks

Example:

For convenience, the commands in this section are condensed below with example values. Variables must be changed to match each environment.

Note:ADQ configuration might be application-specific depending on whether the application is single-threaded or multi-threaded. Different tunings or filtering methods might apply. See specific application sections in this document for further reference. #Variables: #The interface in use. iface=ens8f1 #The path to TC installation (default /usr/sbin). pathtotc="/usr/sbin" #The path to the ice driver package. pathtoicepackage=/opt/ice-1.8.8 #The number of queues for default traffic (for example, 2). num_queues_tc0=2 #The number of queues for application traffic class (also maximum number of application threads to be run). num_queues_tc1=8 #The IP Address of the interface under test on the SUT. ipaddrserver=13.100.2.13 #The starting port of the application (any high numbered port). app_port=6000 #Name of Linux cgroup. cgroup_name=app_tc1 #Command to run inside cgroup on SUT. command=servercmd #Commands (using prio=1 for tc1): ${pathtotc}/tc qdisc add dev $iface root mqprio num_tc 2 map 0 1 queues \ $num_queues_tc0@0 $num_queues_tc1@$num_queues_tc0 hw 1 mode channel sleep 5 ${pathtotc}/tc qdisc add dev $iface clsact ${pathtotc}/tc filter add dev $iface protocol ip ingress prio 1 flower dst_ip \ ${ipaddrserver}/32 ip_proto tcp dst_port $app_port skip_sw hw_tc 1 ${pathtotc}/tc qdisc show dev $iface ${pathtotc}/tc filter show dev $iface ingress ethtool --coalesce ${iface} adaptive-rx off rx-usecs 0 ethtool --coalesce ${iface} adaptive-tx off tx-usecs 500 ethtool --show-coalesce $iface ${pathtoicepackage}/scripts/set_irq_affinity -X all $iface ${pathtoicepackage}/scripts/set_xps_rxqs $iface #ice version 1.7.X (and earlier): ethtool --set-priv-flags $iface channel-inline-flow-director on #ice version 1.8.X (and later): iface_bdf=$(ethtool -i ${iface} | grep bus-info | awk '{print $2}') devlink dev param set pci/${iface_bdf} name tc1_inline_fd value true cmode runtime cgcreate -g net_prio:${cgroup_name} cgset -r net_prio.ifpriomap="$iface 1" ${cgroup_name} cgexec -g net_prio:${cgroup_name} --sticky $command cat /sys/fs/cgroup/net_prio/${cgroup_name}/net_prio.ifpriomap cat /sys/fs/cgroup/net_prio/${cgroup_name}/tasks