Mit Onload arbeiten

Auf dieser Seite wird beschrieben, wie Sie Onload mit U4 Compute Engine-Instanzen verwenden.

Über Onload

Onload ist ein leistungsstarker Netzwerk stack für latenzempfindliche Anwendungen, die eine extrem niedrige Latenz, minimalen Jitter und eine gleichbleibende Leistung erfordern. Onload bietet eine TCP/IP-Implementierung, die den Betriebssystemkernel umgeht und direkt im Userspace ausgeführt wird, während Anwendungen Standard-BSD-Socket-APIs verwenden können.

Die Verwendung von Onload mit der ULL-Lösung umfasst die Unterstützung für Folgendes:

Hinweis

Bevor Sie Onload auf U4 Compute Engine-Instanzen verwenden können, müssen die folgenden Voraussetzungen erfüllt sein.

U4-Instanz erstellen

Wenn Sie noch keine U4 Compute Engine-Instanz erstellt haben, tun Sie dies jetzt mit einer der folgenden Methoden, die die erforderliche Konfiguration für Onload enthalten:

Mit SSH eine Verbindung zur Instanz herstellen

Wenn Sie noch keine Verbindung zu Ihrer Instanz hergestellt haben, stellen Sie jetzt eine Verbindung her mit SSH.

Zum Root-Nutzer wechseln

Die Befehle und Skripts in den folgenden Schritten ändern Einstellungen auf Systemebene, Kernelparameter und Netzwerkschnittstellen. Damit sie erfolgreich ausgeführt werden können, müssen Sie sie als Root-Nutzer ausführen. Sie können zu einer Root-Shell wechseln, indem Sie sudo suausführen, oder bei Bedarf sudovor die Befehle setzen.

Onload einrichten

In diesem Abschnitt werden die Schritte beschrieben, die zum Einrichten von Onload auf einer U4-Instanz erforderlich sind.

Abhängigkeiten installieren

  1. Wenn Sie Rocky Linux verwenden, aktivieren Sie das CodeReady Builder-Repository (CRB). Wenn Sie Red Hat Enterprise Linux (RHEL) verwenden, überspringen Sie diesen Schritt.

    dnf -y config-manager --enable crb
    
  2. Installieren Sie die erforderlichen Abhängigkeiten für Onload:

    dnf -y install git clang \
       python3-setuptools \
       linuxptp \
       libcap-devel libbpf-devel libxdp-devel
    

Onload-Quelle abrufen

Führen Sie die folgenden Befehle aus, um das onload-Repository mit den erforderlichen Änderungen abzurufen:

umask 0022
mkdir -p /usr/src/

git clone https://github.com/Xilinx-CNS/onload /usr/src/onload

# 9.2.0.43 / 9.2.1, origin/v9_2 as of May 18, 2026
git -C /usr/src/onload checkout origin/v9_2

# Pull Google-specific Onload changes not yet merged as of v9_2
curl -L https://github.com/Xilinx-CNS/onload/pull/279.patch | git -C /usr/src/onload am
curl -L https://github.com/Xilinx-CNS/onload/pull/282.patch | git -C /usr/src/onload am
curl -L https://github.com/Xilinx-CNS/onload/pull/325.patch | git -C /usr/src/onload am
curl -L https://github.com/Xilinx-CNS/onload/pull/327.patch | git -C /usr/src/onload am

Onload erstellen

Führen Sie die folgenden Befehle aus, um Onload zu erstellen:

cd /usr/src/onload
USEONLOADEXT=1 ./scripts/onload_install --no-sfc

pushd ./src/tools/bpf_link_helper
clang xdp_onload_prepare.c  -lbpf -o xdp_onload_prepare
clang -target bpf -O2 -g -c xdp_tstamp.c -o ./xdp_tstamp.o
popd

IBT (Indirect Branch Tracking) deaktivieren

IBT muss deaktiviert sein, um Onload wie unter Inkompatibilität mit IBT (Indirect Branch Tracking) beschrieben zu verwenden.

Führen Sie die folgenden Befehle aus, um IBT zu deaktivieren:

grubby --args="ibt=off" --update-kernel=ALL
reboot

Onload laden

In diesem Abschnitt wird beschrieben, wie Sie Onload auf Ihre Instanz laden.

Onload auf einer U4P- oder U4C-Instanz laden

Verwenden Sie das folgende Skript, um Onload auf eine U4P- oder U4C-Bare-Metal-Instanz zu laden.

IFNAMES=($( find /sys/class/net -type l -not -lname '*virtual*' -printf '%l %f\n' | sort | awk '{print $2}'))

for IFNAME in "${IFNAMES[@]}"; do
  ethtool -L "${IFNAME}" rx 16 tx 16
  ethtool -G "${IFNAME}" rx 1024 rx-buf-len 2048
  ethtool -K "${IFNAME}" ntuple on
  echo 0 > "/sys/class/net/${IFNAME}/threaded"
  /usr/src/onload/src/tools/bpf_link_helper/xdp_onload_prepare \
    "${IFNAME}" /usr/src/onload/src/tools/bpf_link_helper/xdp_tstamp.o
done

setenforce 0
numactl --cpunodebind=0,2 onload_tool reload --onload-only
for IFNAME in "${IFNAMES[@]}"; do
  echo "${IFNAME}" 16 > /sys/module/sfc_resource/afxdp/register
  until [[ $(cat "/sys/class/net/${IFNAME}/carrier") == 1 ]]; do
    sleep 1
  done
  hwstamp_ctl -i "${IFNAME}" -r 1
done

echo 1 > /sys/module/sfc_resource/parameters/enable_af_xdp_flow_filters
echo 256 > /sys/module/onload/parameters/xdp_headroom
echo -1 > /sys/module/onload/parameters/inject_kernel_gid

Onload auf einer U4S-Instanz laden

Verwenden Sie das folgende Skript, um Onload auf eine U4S-VM-Instanz zu laden.

IFNAME=NIC_NAME
ALLOCATED_QUEUES=ALLOCATED_QUEUES

ethtool -L "$IFNAME" rx "${ALLOCATED_QUEUES}" tx "${ALLOCATED_QUEUES}"
ethtool -G "$IFNAME" rx 1024 rx-buf-len 2048
ethtool -K "$IFNAME" ntuple on
echo 0 > "/sys/class/net/${IFNAME}/threaded"
/usr/src/onload/src/tools/bpf_link_helper/xdp_onload_prepare "$IFNAME" \
  /usr/src/onload/src/tools/bpf_link_helper/xdp_tstamp.o

setenforce 0
numactl --cpunodebind=0 onload_tool reload --onload-only

echo "${IFNAME} ${ALLOCATED_QUEUES}" | tee /sys/module/sfc_resource/afxdp/register
until [[ $(cat "/sys/class/net/${IFNAME}/carrier") == 1 ]]; do
    sleep 1
done
hwstamp_ctl -i "$IFNAME" -r 1

echo 1 > /sys/module/sfc_resource/parameters/enable_af_xdp_flow_filters
echo 256 > /sys/module/onload/parameters/xdp_headroom
echo -1 > /sys/module/onload/parameters/inject_kernel_gid

Ersetzen Sie Folgendes:

  • NIC_NAME: der Name der Netzwerkschnittstelle im Betriebssystem, z. B. enp22s0f0.
  • ALLOCATED_QUEUES: die Anzahl der Empfangs- (RX) und Übertragungswarteschlangen (TX), die für Onload auf der Netzwerkschnittstelle zugewiesen werden sollen. Legen Sie diesen Wert auf die Hälfte der Gesamtzahl der RX- oder TX-Warteschlangen fest, die der vNIC zugewiesen sind.

    Bei U4S-Instanzen entspricht die Gesamtzahl der Warteschlangen (für RX- bzw. TX-Warteschlangen) num_vcpus / num_vnics, maximal jedoch 16 Warteschlangen pro vNIC. Wenn die vNIC beispielsweise 4 TX-Warteschlangen hat, legen Sie diesen Wert auf 2 fest. Wenn die vNIC 16 TX-Warteschlangen hat, legen Sie diesen Wert auf 8 fest.

    Weitere Informationen zur Standardzuweisung von Warteschlangen finden Sie unter Empfangs- und Übertragungswarteschlangen.

Onload-Flags konfigurieren

Um die Leistung zu optimieren und die Latenz zu verringern, können Sie beim Ausführen Ihrer Anwendungen mit Onload die folgenden Umgebungsvariablen und Flags verwenden. Dieser Abschnitt enthält empfohlene Einstellungen, die Sie nach Bedarf für Ihre Anwendungen anpassen können.

Sie müssen diese Parameter vor den Befehlen Ihrer Anwendung angeben. Wenn Sie beispielsweise eine Anwendung mit diesen Einstellungen ausführen möchten, verwenden Sie das folgende Format:

env EF_NO_FAIL=0 \
  EF_POLL_USEC=100000 \
  EF_RX_TIMESTAMPING=3 \
  EF_MAX_ENDPOINTS=1048576 \
  EF_WODA_SINGLE_INTERFACE=1 \
  EF_UL_EPOLL=3 \
  EF_USE_HUGE_PAGES=0 \
  EF_EPOLL_CTL_HANDOFF=0 \
  EF_FDS_MT_SAFE=0 \
  EF_NONAGLE_INFLIGHT_MAX=-1 \
  EF_RXQ_SIZE=4096 \
  EF_TCP_RCVBUF_ESTABLISHED_DEFAULT=65536 \
  EF_MAX_PACKETS=65536 \
  EF_PREFAULT_PACKETS=65536 \
  EF_EVS_PER_POLL=256 \
  onload -v --profile=latency APPLICATION_COMMAND

Onload entfernen

Verwenden Sie das folgende Skript, um Onload zu entfernen.

IFNAMES=($( find /sys/class/net -type l -not -lname '*virtual*' -printf '%l %f\n' | sort | awk '{print $2}'))

for IFNAME in "${IFNAMES[@]}"; do
  rm -f "/sys/fs/bpf/onload_xdp_xsk_${IFNAME}"
done

onload_tool unload --onload-only

for IFNAME in "${IFNAMES[@]}"; do
  # (optional) Disable threaded busypolling in case it's up. See busypolling
  # section
  echo 0 > "/sys/class/net/${IFNAME}/threaded"

  ip link set dev "${IFNAME}" xdp off
done

Einen systemd-Dienst konfigurieren, der Onload automatisch startet

Wenn Onload beim Starten Ihrer Instanz automatisch gestartet werden soll, können Sie es als systemd Dienst registrieren. Erstellen Sie eine Dienstdatei mit folgender Vorlage:

[Unit]
Description=ULL Solution -- Loading & instance tuning for Onload
After=network-online.target
After=google-guest-agent-manager.service google-guest-agent.service
Before=multi-user.target
Before=sshd.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=START_SCRIPT_PATH
ExecStartPost=OPTIMIZATION_SCRIPT_PATH
ExecStop=STOP_SCRIPT_PATH

[Install]
WantedBy=multi-user.target

Ersetzen Sie Folgendes:

  • START_SCRIPT_PATH: der Pfad zum Skript, das Onload startet, z. B. eines der Skripts unter Onload laden.
  • OPTIMIZATION_SCRIPT_PATH: der Pfad zum optionalen Skript, das Optimierungskonfigurationen anwendet. Bei Bedarf können Sie ein Skript erstellen, das Ihre Leistungsoptimierungen enthält, und es hier einfügen. Andernfalls können Sie die Zeile entfernen, die diese Variable enthält.
  • STOP_SCRIPT_PATH: der Pfad zum Skript, das Onload beendet, z. B. das Skript unter Onload entfernen.

Busy Polling konfigurieren

In diesem Abschnitt finden Sie Beispiele für die Konfiguration von Busy Polling auf Ihrer Instanz.

Beim Busy Polling wird kontinuierlich nach neuen Netzwerkpaketen gesucht, anstatt auf Geräteunterbrechungen zu warten. Dadurch werden Latenz und Jitter reduziert. Weitere Informationen zum Busy Polling finden Sie in der Linux-Kernel-Dokumentation unter Busy Polling.

Die RX-Warteschlange abrufen, die von einem Onload-Stack verwendet wird

So rufen Sie die RX-Warteschlange ab, die von einem Onload-Stack verwendet wird:

  1. Rufen Sie die Onload-Stack-ID mit onload_stackdump ab:

    onload_stackdump
    
  2. Da die Onload-Stack-ID und die NAPI-Warteschlangen-ID nicht immer übereinstimmen, verwenden Sie das folgende Skript, um den entsprechenden Schnittstellennamen, Index und die Warteschlangen-ID aus einer Stack-ID abzurufen.

    ONLOAD_STACK=ONLOAD_STACK_ID
    
    INTF_HWPORT_MAP=($(onload_stackdump "${ONLOAD_STACK}" netif_extra | grep -oP "intf_i_to_hwport=\K.*$" | tr ',' '\n'))
    HWPORT_IFINDEX_MAP=($(onload_stackdump "${ONLOAD_STACK}" hwport_to_base_ifindex | grep -oP "\d+$"))
    while read -r INTF_ID QUEUE_ID; do
    HW_PORT="${INTF_HWPORT_MAP[INTF_ID]}"
    IFINDEX="${HWPORT_IFINDEX_MAP[HW_PORT]}"
    IFNAME=$(ip -j link | jq -r ".[] | select(.ifindex == ${IFINDEX}) | .ifname")
    echo "ifname=${IFNAME} ifindex=${IFINDEX} queue_id=${QUEUE_ID}"
    done < <(onload_stackdump "${ONLOAD_STACK}" netif | grep -oP "((intf|vi)=)\K\d+" | xargs -n 2)

    Ersetzen Sie ONLOAD_STACK_ID durch die ID des Stacks, für den Sie Busy Polling aktivieren oder deaktivieren möchten.

  3. Notieren Sie sich die Werte, die Sie verwenden, wenn Sie Busy Polling in den folgenden Abschnitten aktivieren oder deaktivieren.

Busy Polling für eine RX-Warteschlange aktivieren

In diesem Abschnitt finden Sie ein Beispiel dafür, wie Sie Busy Polling für eine bestimmte RX-Warteschlange aktivieren können, die von einem Onload-Stack verwendet wird.

  1. Führen Sie das folgende Bash-Skript in Ihrem Terminal aus. Die Funktion enable_single_queue führt folgende Schritte aus:

    • Ruft die napi_id ab, die einer RX-Warteschlange entspricht, indem sie Netlink (ynl) verwendet.
    • Legt die Eigenschaft threaded: busy-poll für die napi_id fest.
    • Ruft die kthread_pid des Threads ab, der die napi_id busy pollt.
    • Verwendet taskset, um die kthread_pid an eine bestimmte CPU zu binden.
    readonly NETDEV_YAML=${NETDEV_YAML:-"/usr/share/ynl/specs/netdev.yaml"}
    
    call_ynl() {
      ynl --spec "${NETDEV_YAML}" "$@"
    }
    
    enable_single_queue() {
      local -r interface="$1"
      local -r ifindex=$(cat "/sys/class/net/${interface}/ifindex")
      local -r q_id="$2"
      local -r cpu="$3"
    
      local napi_id
      napi_id=$(call_ynl --output-json --do queue-get \
        --json "{\"ifindex\": ${ifindex}, \"id\": ${q_id}, \"type\": \"rx\"}" | \
        jq -r '."napi-id"')
    
      if [[ -z "${napi_id}" || "${napi_id}" == "null" ]]; then
        echo "Error: No napi_id found for queue ${q_id} on interface ${interface}" >&2
        exit 1
      fi
    
      echo "Enabling busypolling for queue ${q_id} (NAPI ${napi_id}) on CPU ${cpu}"
      call_ynl --do napi-set --json "{\"id\": \"${napi_id}\", \"threaded\": \"busy-poll\"}" >/dev/null
    
      local napi_kthread_pid
      napi_kthread_pid=$(call_ynl --do napi-get --output-json \
        --json "{\"id\": \"${napi_id}\"}" | jq -r '."pid" // empty')
    
      if [[ -z "${napi_kthread_pid}" ]]; then
        echo "Error: Could not get PID for NAPI ${napi_id}" >&2
        exit 1
      fi
    
      taskset -pc "${cpu}" "${napi_kthread_pid}" >/dev/null
    }
  2. Führen Sie den folgenden Befehl aus, um die Funktion enable_single_queue aufzurufen:

    enable_single_queue NIC_NAME QUEUE_ID CPU_ID
    

    Ersetzen Sie Folgendes:

    • NIC_NAME: der Name der Netzwerkschnittstelle im Betriebssystem, z. B. ens8f0.
    • QUEUE_ID: die zuvor abgerufene Warteschlangen-ID.
    • CPU_ID: die ID der CPU, auf der der Busy Polling-Thread ausgeführt werden soll, z. B. 5.
  3. Stellen Sie sicher, dass Sie Ereignisse zur Neuerstellung von Threads einplanen , die sich auf Ihre Busy Polling-Konfiguration auswirken können.

Ereignisse zur Neuerstellung von Threads einplanen

Wenn der Kernel einen Thread neu erstellt, bleiben die zugehörigen Threadkonfigurationen nicht erhalten, z. B. die CPU-Affinitätsmaske und die Planungsrichtlinie. Ereignisse wie die folgenden führen dazu, dass der Kernel einen Thread neu erstellt, der NAPI busy pollt:

  • Link-Flaps/-Resets
  • XDP-Programmanhänge (z. B. beim Ausführen der Skripts zum Laden von Onload oder beim Anhängen benutzerdefinierter XDP-Programme)
  • Änderungen der Ringparameter (ethtool -G)
  • Änderungen der Warteschlangenzahl (ethtool -L)

Um Probleme zu vermeiden, sollten Sie Aufgaben vermeiden, die während des normalen Betriebs Ereignisse zur Neuerstellung von Threads verursachen.

Damit Ihre Busy Polling-Konfiguration nach der Neuerstellung eines Threads erhalten bleibt, müssen Sie die neue Prozess-ID (PID) des Threads abrufen und ihn wieder an die CPU binden. Dazu können Sie die enable_single_queue Funktion noch einmal ausführen.

Busy Polling für eine RX-Warteschlange deaktivieren

In diesem Abschnitt finden Sie ein Beispiel dafür, wie Sie Busy Polling für eine bestimmte RX-Warteschlange deaktivieren können, die von einem Onload-Stack verwendet wird.

  1. Rufen Sie die RX-Warteschlange ab, die von einem Onload-Stack verwendet wird, indem Sie onload_stackdump ausführen:

    onload_stackdump
    
  2. Führen Sie das folgende Bash-Skript in Ihrem Terminal aus. Die Funktion disable_single_queue führt folgende Schritte aus:

    • Ruft die napi_id ab, die einer RX-Warteschlange entspricht, indem sie Netlink (ynl) verwendet.
    • Setzt die Thread-Eigenschaft der napi_id auf disabled.
    disable_single_queue() {
      local -r interface="$1"
      local -r ifindex=$(cat "/sys/class/net/${interface}/ifindex")
      local -r q_id="$2"
    
      local napi_id
      napi_id=$(call_ynl --output-json --do queue-get \
        --json "{\"ifindex\": ${ifindex}, \"id\": ${q_id}, \"type\": \"rx\"}" | \
        jq -r '."napi-id"')
    
      if [[ -z "${napi_id}" || "${napi_id}" == "null" ]]; then
        echo "Error: No napi_id found for queue ${q_id} on interface ${interface}" >&2
        exit 1
      fi
    
      echo "Disabling busypolling for queue ${q_id} (NAPI ${napi_id})"
      call_ynl --do napi-set --json "{\"id\": \"${napi_id}\", \"threaded\": \"disabled\"}" >/dev/null
    }
  3. Führen Sie den folgenden Befehl aus, um die Funktion disable_single_queue aufzurufen:

    disable_single_queue NIC_NAME QUEUE_ID
    

    Ersetzen Sie Folgendes:

    • NIC_NAME: der Name der Netzwerkschnittstelle im Betriebssystem, z. B. ens8f0.
    • QUEUE_ID: die zuvor abgerufene Warteschlangen-ID.

Busy Polling-Status einer Warteschlange abrufen

Mit den folgenden Befehlen können Sie den NAPI-Status einer Warteschlange prüfen, um festzustellen, ob sie busy pollt:

IFNAME=NIC_NAME
QUEUE_ID=QUEUE_ID
QUEUE_TYPE=QUEUE_TYPE

IFINDEX=$(cat "/sys/class/net/${IFNAME}/ifindex")
NAPI_ID=$(ynl --spec /usr/share/ynl/specs/netdev.yaml \
  --output-json --do queue-get \
  --json '{"ifindex": '${IFINDEX}', "id": '${QUEUE_ID}', "type": "'${QUEUE_TYPE}'"}' | \
  jq '."napi-id"')
ynl --spec /usr/share/ynl/specs/netdev.yaml \
  --output-json --do napi-get \
  --json '{"id": '${NAPI_ID}'}' | jq -r '"status: \(.threaded)"'

Ersetzen Sie Folgendes:

  • NIC_NAME: der Name der Netzwerkschnittstelle im Betriebssystem, z. B. ens8f0.
  • QUEUE_ID: die ID der Warteschlange, die Sie prüfen möchten.
  • QUEUE_TYPE: rx oder tx.

Leistung optimieren

In diesem Abschnitt finden Sie allgemeine Anleitungen zur Optimierung der Leistung Ihrer U4-Bare-Metal-Instanzen (U4P und U4C). Passen Sie die Beispiele in dieser Anleitung nach Bedarf für Ihre Arbeitslasten an.

NUMA-Topologie für U4-Bare-Metal-Instanzen prüfen

In der folgenden Tabelle wird beschrieben, welche Netzwerkschnittstellen welche NUMA-Knoten für U4-Bare-Metal-Instanzen verwenden:

NIC (Google Cloud Name) NIC (Name im Betriebssystem) NUMA-Knoten PCIE BDF
nic0 enp22s0f0 0 0000:16:00.0
nic1 ens8f0 0 0000:27:00.0
nic2 ens48f0 2 0000:b8:00.0

Die obige Tabelle enthält typische vom Betriebssystem zugewiesene Namen für Netzwerkschnittstellen für RHEL. Die tatsächlichen Namen können abweichen.

CPU-Isolierungsschema bestimmen

Für eine optimale Leistung empfehlen wir, Folgendes zu isolieren:

  • Die CPUs, die von Ihrer Anwendung verwendet werden
  • Die CPUs, die zum Busy Polling der Onload-RX-Warteschlangen verwendet werden
  • Die CPUs, die für Kernel- und Treiberunterbrechungen verwendet werden

Die folgende Tabelle enthält ein Beispiel dafür, wie Sie CPUs auf U4-Bare-Metal-Instanzen isolieren können. Passen Sie die Zuordnung nach Bedarf für Ihre Arbeitslasten an. Möglicherweise benötigen Sie beispielsweise mehr Anwendungs-CPUs.

Zweck CPUs
Allgemeine Kernelunterbrechungen 0,1,30,31,60,61,90,91
nic0-Treiberunterbrechungen für Warteschlangen 0–11 2
nic1-Treiberunterbrechungen für Warteschlangen 0–11 3
nic0- und nic1-Treiberunterbrechungen für Warteschlangen 12–15 4
nic1-Busy Polling 5–16
nic1-Anwendungsthreads (Onload) 17–29
nic0-Busy Polling 32–43
nic0-Anwendungsthreads (Onload) 44–59
nic2-Treiberunterbrechungen für Warteschlangen 0–11 62
nic2-Treiberunterbrechungen für Warteschlangen 12–15 63
nic2-Busy Polling 64–75
nic2-Anwendungsthreads (Onload) 76–89

Abhängigkeiten für die Leistungsoptimierung installieren

Führen Sie den folgenden Befehl aus, um die erforderlichen Abhängigkeiten für die Leistungsoptimierung zu installieren:

dnf -y install numactl tuna jq

Kernel-Bootparameter konfigurieren

Führen Sie den folgenden Befehl aus, um CPUs von der Kernelplanung zu isolieren. Dadurch wird auch die Intel QuickAssist Technology (QAT) deaktiviert, damit sie nicht mit Ihren isolierten Kernen in Konflikt gerät.

Der folgende Beispielbefehl isoliert die CPUs 2-29, 32-59 und 62-89 und weist 0,1,30,31,60,61,90,91 für allgemeine Kernelunterbrechungen zu. Diese Werte entsprechen dem Beispiel-CPU-Isolierungsschema. Ersetzen Sie die Werte nach Bedarf entsprechend Ihrem CPU-Isolierungsschema.

grubby --args="isolcpus=domain,managed_irq,2-29,32-59,62-89 nohz=on nohz_full=2-29,32-59,62-89 rcu_nocbs=2-29,32-59,62-89 irqaffinity=0,1,30,31,60,61,90,91 rcu_nocb_poll modprobe.blacklist=intel_qat,qat_4xxx" --update-kernel=ALL
reboot

CPU-Isolierung nach dem Booten konfigurieren

Führen Sie den folgenden Befehl aus, um CPUs nach dem Booten zu isolieren. Die Werte entsprechen dem Beispiel-CPU-Isolierungsschema. Ersetzen Sie die Werte nach Bedarf entsprechend Ihrem CPU-Isolierungsschema.

tuna isolate -c 2-29,32-59,62-89

Warteschlangenunterbrechungen bestimmten CPUs zuweisen

In diesem Abschnitt wird beschrieben, wie Sie gve-Warteschlangenunterbrechungsanfragen (Interrupt Requests, IRQs) an bestimmte CPUs verschieben. Der gve-Treiber wird vom Netzwerkschnittstellentyp GVNIC in Google Cloudverwendet.

  1. Bestimmen Sie die IRQs für eine bestimmte Netzwerkschnittstelle und einen bestimmten Warteschlangenbereich. Sehen Sie sich das folgende Bash-Beispiel an, in dem eine Funktion irq_list definiert wird.

    irq_list() {
      local ifname=$1
      local queue_begin=$2
      local queue_end=$3
    
      pci_name=$(basename $(readlink /sys/class/net/${ifname}/device))
      rx_ntfy_blk_start=$(ethtool -l "${ifname}" | awk '
        /Pre-set maximums:/ { in_preset = 1 }
        /Current hardware settings:/ { in_preset = 0 }
        in_preset && $1 == "RX:" { rx = $2 }
        in_preset && $1 == "TX:" { tx = $2 }
        END { print int((rx + tx) / 2) }
      ')
      for i in $(seq "${queue_begin}" "${queue_end}"); do
        irq_tx="gve-ntfy-blk${i}@pci:${pci_name}"
        irq_rx="gve-ntfy-blk$(($i + rx_ntfy_blk_start))@pci:${pci_name}"
        # gve IRQ names are stored in a char[IFNAMSIZ + 16] so capped to 31 characters.
        echo "${irq_tx:0:31}"
        echo "${irq_rx:0:31}"
      done | paste -sd ','
    }
  2. Weisen Sie IRQs entsprechend Ihrem CPU-Isolierungsschema der entsprechenden CPU zu. Das folgende Beispielskript verwendet tuna und die Funktion irq_list aus dem vorherigen Schritt:

    tuna move -c 2 -q "$(irq_list enp22s0f0 0 11)"
    tuna move -c 4 -q "$(irq_list enp22s0f0 12 15)"
    
    tuna move -c 3 -q "$(irq_list ens8f0 0 11)"
    tuna move -c 4 -q "$(irq_list ens8f0 12 15)"
    
    tuna move -c 62 -q "$(irq_list ens48f0 0 11)"
    tuna move -c 63 -q "$(irq_list ens48f0 12 15)"

Betriebssystem- und Geräteeinstellungen konfigurieren

  1. Führen Sie das folgende Skript aus, um Einstellungen zu konfigurieren, die die Latenz minimieren und verhindern, dass Standardverhalten des Betriebssystems Ihre Onload-Konfigurationen beeinträchtigen.

    echo 0 > /proc/sys/net/core/busy_poll
    echo 0 > /proc/sys/net/core/busy_read
    echo 0 > /proc/sys/kernel/timer_migration
    echo 0 > /proc/sys/net/core/rps_sock_flow_entries
    echo -1 > /proc/sys/kernel/sched_rt_runtime_us
    
    for IFNAME in "${IFNAMES[@]}"; do
      ethtool -C "${IFNAME}" rx-usecs 0 tx-usecs 0
      echo 0 > "/sys/class/net/${IFNAME}/napi_defer_hard_irqs"
      echo 15000 > "/sys/class/net/${IFNAME}/gro_flush_timeout"
    done
  2. Verwenden Sie RSS (ethtool -X), um Traffic von Warteschlangen wegzuleiten, die für Onload-Arbeitslasten vorgesehen sind. Das folgende Beispielskript basiert auf den Werten im Beispiel-CPU-Isolierungsschema. Da Onload die Warteschlangen 0-11 verwendet, leitet das Skript den gesamten anderen Traffic an die Warteschlangen 12-15 weiter.

    for IFNAME in "${IFNAMES[@]}"; do
      ethtool -X "${IFNAME}" weight 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
    done

Nächste Schritte

  • Informationen zum Synchronisieren der Systemuhr Ihrer Instanz mit der Uhr der physischen NIC ihres Hostservers finden Sie unter Genaue Zeit konfigurieren.