Tous les produits
Search
Centre de documentation

:Personnaliser le RSS pour les ENI

Dernière mise à jour :Aug 18, 2026

Personnalisez les règles de hachage RSS et les tables d'indirection sur les ENI prises en charge afin de répartir uniformément le trafic entre les cœurs CPU et de résoudre les goulots d'étranglement liés à un cœur unique.

Qu'est-ce que le RSS

Le Receive Side Scaling (RSS) s'appuie sur le matériel et le pilote de l'ENI pour calculer une valeur de hachage à partir des caractéristiques des paquets (adresses IP source/destination et ports), puis mappe différents flux de trafic vers plusieurs files RX. Les cœurs CPU associés traitent ces files en parallèle, ce qui permet d'équilibrer la charge et de réduire la latence liée à l'utilisation d'un seul cœur.

Une ENI qui prend en charge les files d'attente multiples utilise des canaux RX (réception) et TX (envoi) indépendants par file pour un traitement parallèle. Lorsqu'un paquet arrive, le matériel de l'ENI applique une politique RSS pour distribuer les différents flux de données entre plusieurs files RX. Par défaut, la politique RSS d'une instance ECS est fixée dans le Virtual Private Cloud (VPC) et ne peut ni être affichée ni modifiée depuis l'instance elle-même.

Certaines familles d'instances prennent en charge la fonctionnalité de RSS personnalisé pour les ENI. Après avoir activé la fonctionnalité de RSS personnalisé sur une famille d'instances prise en charge, l'ENI distribue le trafic selon les règles de hachage personnalisées par défaut. Vous pouvez également ajuster la configuration RSS en fonction des caractéristiques réelles de votre trafic.

Une fois le RSS personnalisé activé, vous pouvez aussi configurer le RSS dans les scénarios DPDK afin de maximiser les performances multicœurs.

Fonctionnement

Le RSS personnalisé pour une ENI d'instance ECS fonctionne comme suit :

  • Calcul de la valeur de hachage : l'ENI calcule une valeur de hachage à partir du quintuplet (IP source, IP destination, port source, port destination et protocole), d'une clé de hachage et d'un algorithme de hachage.

    • Clé de hachage : une valeur fixe de 40 octets. Le pilote de l'ENI génère une clé de hachage par défaut lors de l'initialisation. Vous pouvez ajuster la clé de hachage pour influencer la répartition du trafic.

    • Algorithme de hachage : seul l'algorithme toeplitz par défaut est actuellement pris en charge. Ce paramètre ne peut pas être modifié.

    • Règles de hachage : les règles de calcul des valeurs de hachage varient selon le type de trafic. Les règles de hachage par défaut du RSS des ENI ECS sont les suivantes. Vous ne pouvez pas modifier ces règles.

      • Trafic TCP et UDP sur IPv4/IPv6 : une valeur de hachage est calculée sur la base du quadruplet (IP source, IP destination, port source et port destination) et de la clé de hachage.

      • Trafic non TCP/UDP sur IPv4/IPv6, tel que ICMP : une valeur de hachage est calculée sur la base du doublet (IP source et IP destination) et de la clé de hachage.

      • Les messages non IP (tels que ARP) sont envoyés vers la file par défaut (file 0) et ne font pas l'objet d'un hachage.

  • Mappage de la table d'indirection : la table d'indirection RSS est un tableau prédéfini qui associe les valeurs de hachage aux files de réception de destination. Chaque élément (bucket de hachage) stocke un numéro de file, par exemple 0, 1 ou 2. Lors du chargement du pilote de l'ENI, une table d'indirection est automatiquement générée afin de répartir uniformément le trafic.

    • Longueur de la table d'indirection : nombre total de buckets de hachage. La valeur est fixée à 128.

    • Modes de distribution :

      Le mode de distribution de la table d'indirection RSS constitue le mécanisme central qui associe les valeurs de hachage à des files de réception spécifiques. Grâce à une table d'indirection prédéfinie, le résultat du calcul de hachage est converti en un index de file. Cela permet une répartition flexible du trafic entre plusieurs cœurs.

      Différents modes de distribution, tels que la distribution uniforme et la distribution pondérée, influencent directement la manière dont le trafic est réparti entre les cœurs CPU. Cela a un impact sur le débit du système, la latence, l'utilisation des ressources et les performances des services.

      Choisissez un modèle de distribution adapté à votre scénario. Consultez la section Modèle de distribution de la table d'indirection.

    • Processus de mappage de la table d'indirection :

      1. Calcul de l'index du bucket de hachage : Index = Valeur de hachage % Longueur de la table d'indirection (par exemple, 88 % 128 → index 88). Vous pouvez utiliser le script de calcul RSS pour calculer la valeur de l'index.

      2. Remplissage des numéros de file : inscrivez les numéros de file dans chaque bucket de hachage selon le mode de distribution choisi.

        Une fois la table d'indirection générée, l'index de hachage de chaque paquet correspond à un numéro de file, et le paquet est envoyé vers cette file.

  • Association aux cœurs CPU : lorsqu'une file reçoit un paquet, elle déclenche une interruption. Le cœur CPU associé traite cette interruption.

    Les images autres que Red Hat Enterprise Linux prennent en charge par défaut l'affinité des interruptions réseau. Chaque file est associée à une interruption indépendante, et l'affinité des interruptions répartit leur traitement entre différents cœurs CPU. Consultez le Mécanisme central des files d'attente multiples.

Activer ou désactiver le RSS personnalisé pour une ENI

Important

La fonctionnalité de RSS personnalisé pour les ENI est en aperçu sur invitation. Pour utiliser cette fonctionnalité, vous pouvez soumettre un ticket.

Lorsque vous activez le RSS personnalisé sur un type d'instance pris en charge, le trafic reçu est distribué vers plusieurs files de réception selon les règles de hachage par défaut. Différents cœurs CPU traitent ces files en parallèle, ce qui augmente le débit et réduit la charge sur un cœur unique.

Prérequis

  • Le déploiement du RSS personnalisé s'effectue par phases. Il est disponible dans les régions suivantes :

    Nom de la région

    ID de région

    Chine (Hong Kong)

    cn-hongkong

  • Seules certaines familles d'instances à files d'attente multiples prennent en charge le RSS personnalisé, notamment la famille d'instances à usage général g9i et la famille d'instances optimisées pour la mémoire r9i.

    Appelez l'opération API DescribeInstanceTypes pour vérifier la prise en charge. RssSupport=true indique que la fonctionnalité est prise en charge.

  • L'image Alibaba Cloud Linux 3.2104 LTS 64 bits est recommandée.

    • Si vous utilisez d'autres images publiques, la version du noyau doit être 6,12 ou ultérieure.

    • Si vous utilisez la fonctionnalité de RSS personnalisé dans une application DPDK, la version de DPDK doit être 21,11 ou ultérieure.

Procédure d'activation ou de désactivation

Le RSS personnalisé est désactivé par défaut. Vous pouvez l'activer ou le désactiver lors de la création d'une ENI ou après sa création.

  • Lors de l'appel à CreateNetworkInterface, définissez EnableRss dans EnhancedNetwork sur true ou false.

    Le RSS personnalisé prend effet après l'attachement de l'ENI à une instance.

  • Appelez ModifyNetworkInterfaceAttribute et définissez EnableRss dans EnhancedNetwork sur true ou false. Après l'activation ou la désactivation, la modification prend effet lorsque l'ENI est rattachée :

  • Appelez DescribeNetworkInterfaceAttribute avec Attribute défini sur enhancedNetwork pour savoir si le RSS personnalisé est activé. EnableRSS=true signifie qu'il est activé ; false signifie qu'il est désactivé.

    Si le RSS n'a pas été modifié pour l'ENI, cette opération ne renvoie pas le paramètre EnableRSS, ce qui signifie que la fonctionnalité n'est pas activée.

Afficher la configuration RSS d'une ENI

Après avoir activé le RSS personnalisé, le pilote de l'ENI génère une configuration RSS par défaut selon le mécanisme et les règles par défaut lors du rechargement de l'ENI.

Vous pouvez vous connecter à distance à une instance Linux et exécuter ethtool -x eth0 pour afficher la configuration RSS de l'ENI principale. Pour une ENI secondaire, remplacez l'identifiant d'interface (eth1, eth2, etc.).

image

  • Table de hachage (table d'indirection de hachage de flux RX) : définit les règles de mappage des valeurs de hachage vers les 64 files de réception.

    • Chaque ligne de la table de hachage représente une plage de valeurs de hachage, indiquée par l'index de départ. Par exemple, 0 indique les valeurs de hachage 0-7, et 8 indique 8-15.

    • Les nombres dans la table (0, 1, 2, etc.) représentent les identifiants des files de réception correspondantes. Dans cet exemple, il y a 64 files (0-63).

    • Configuration actuelle : la table d'indirection est remplie cycliquement avec la séquence 0,1,2,...,63,0,1,2...63, ce qui garantit que les valeurs de hachage sont mappées uniformément vers les 64 files et que le trafic est réparti équitablement.

  • Clé de hachage RSS : la clé utilisée pour calculer la valeur de hachage. Les caractères hexadécimaux représentent une clé de 40 octets.

  • Fonction de hachage RSS : définit l'algorithme utilisé pour calculer la valeur de hachage.

    • toeplitz : il s'agit de l'algorithme par défaut, actuellement activé. Il prend en charge le hachage symétrique basé sur un quintuplet et convient au trafic à usage général.

    • xor/crc32 : il s'agit d'autres algorithmes optionnels généralement utilisés dans des scénarios spécifiques. ECS ne prend actuellement en charge que l'algorithme toeplitz ; les autres algorithmes ne sont ni pris en charge ni activés.

  • Règles de hachage : affichez la configuration des champs de hachage pour le trafic reçu par l'ENI principale.

    ethtool  -n eth0 rx-flow-hash tcp4
    • Vous pouvez remplacer tcp4 par le type de protocole que vous souhaitez interroger, tel que udp4, tcp6 ou udp6.

    • Les règles de hachage par défaut du RSS des ENI ECS sont les suivantes. Vous ne pouvez pas modifier ces règles.

      • Trafic TCP et UDP sur IPv4/IPv6 : une valeur de hachage est calculée sur la base du quadruplet (IP source, IP destination, port source et port destination) et de la clé de hachage.

      • Trafic non TCP/UDP sur IPv4/IPv6, tel que ICMP : une valeur de hachage est calculée sur la base du doublet (IP source et IP destination) et de la clé de hachage.

      • Les messages non IP (tels que ARP) sont envoyés vers la file par défaut (file 0) et ne font pas l'objet d'un hachage.

    • Prenons tcp4 comme exemple. Pour le trafic TCP IPv4, la valeur de hachage est calculée par défaut sur la base du quadruplet (IP source, adresse IP destination, port source, port destination) et de la clé de hachage :

      image

      Les caractéristiques attendues du trafic sont les suivantes :

      • Même connexion TCP : tous les paquets ont la même valeur de hachage et sont distribués vers la même file. Cela garantit l'ordre des paquets.

      • Connexions TCP différentes : si les quadruplets diffèrent, les valeurs de hachage diffèrent. Le trafic est distribué vers différentes files. Cela permet à plusieurs cœurs CPU de traiter différentes connexions en parallèle et d'augmenter le débit.

Si le message suivant s'affiche, le RSS personnalisé n'est pas activé ou le type d'instance ne le prend pas en charge. Activez le RSS personnalisé après avoir confirmé que le type d'instance le prend en charge.

image

Configurer le RSS personnalisé pour une ENI

La configuration RSS par défaut répond à la plupart des besoins. Vous devrez peut-être ajuster la clé de hachage ou la table d'indirection dans les situations suivantes :

  • Trafic inégal : les valeurs de hachage par défaut peuvent concentrer un trafic spécifique dans quelques files.

  • Optimisation des performances : ajustez les règles de hachage en fonction des caractéristiques du trafic, par exemple une proportion élevée de UDP, afin d'améliorer l'utilisation des files.

  • Exigences de sécurité : utilisez une clé de hachage personnalisée pour empêcher les attaquants de prédire la répartition du trafic.

Important
  • Dans cet exemple, l'instance est configurée avec l'image Alibaba Cloud Linux 3.2104 LTS 64-bit.

  • Cet exemple utilise l'ENI principale eth0. Remplacez l'identifiant d'interface par eth1 ou eth2 pour modifier le RSS de l'ENI secondaire correspondante.

  • Lorsque la configuration RSS ne correspond pas aux caractéristiques de votre trafic, elle peut entraîner une répartition inégale et une contention d'état inter-cœurs, ce qui affecte les performances. Ajustez la configuration en fonction des caractéristiques réelles du trafic et utilisez les outils de surveillance pour observer la répartition des files en temps réel.

Configurer la clé de hachage

Regénérez la clé de hachage RSS si le trafic est réparti de manière inégale (par exemple, si rx_packets de certaines files est nettement supérieur à celui d'autres files), ou pour empêcher les attaquants de déduire les modèles de trafic en effectuant une ingénierie inverse de la valeur de hachage.

Important

La modification de la clé change les valeurs de hachage des connexions existantes, ce qui peut provoquer temporairement un réordonnancement ou des retransmissions de paquets. Effectuez cette opération pendant les heures creuses.

  1. Affichez la clé de hachage actuelle de l'ENI.

    Le pilote de l'ENI génère une clé de hachage par défaut de 40 octets lors du chargement de l'ENI.

    ethtool -x eth0

    image

  2. Générez une nouvelle clé aléatoire à l'aide d'OpenSSL.

    openssl rand -hex 40 | fold -w2 | paste -sd: -
  3. Appliquez la nouvelle clé à l'ENI.

    Important

    Il s'agit d'un paramètre temporaire. Il devient invalide après le redémarrage de l'instance ou le rattachement de l'ENI. Le pilote de l'ENI initialise automatiquement une configuration par défaut aléatoire.

    ethtool -X eth0 hkey <hash key>

    Remplacez <hash key> par la nouvelle clé que vous avez générée à l'étape précédente.

  4. Vérifiez que la nouvelle clé a pris effet.

    ethtool -x eth0

    La sortie indique que la nouvelle clé a pris effet :

    image

Configurer la table d'indirection

Le mode de distribution de la table d'indirection RSS constitue le mécanisme central qui associe les valeurs de hachage à des files d'attente de réception spécifiques. Grâce à une table d'indirection prédéfinie, le résultat du calcul de hachage est converti en un index de file d'attente. Cette approche permet une répartition flexible du trafic sur plusieurs cœurs.

Les différents modes de distribution, tels que la distribution uniforme et la distribution pondérée, influencent directement la manière dont le trafic est réparti entre les cœurs CPU. Cela a un impact immédiat sur le débit du système, la latence, l'utilisation des ressources et les performances des services.

Choisissez un mode de distribution adapté à votre scénario.

Important

Les configurations suivantes sont temporaires. Elles deviennent invalides après le redémarrage de l'instance ou le rattachement de l'ENI. Le pilote ENI réinitialise alors une configuration par défaut aléatoire.

  • Mode de distribution uniforme : Les N premières files d'attente remplissent les compartiments de hachage de manière cyclique. Ce mode convient aux scénarios de forte concurrence générale.

    ethtool -X eth0 equal <Number of queues N>

    Si la valeur est définie sur 64, la table d'indirection est remplie cycliquement avec 0,1,2,...,63,0,1,2...63,.

    image

  • Distribution pondérée : Allouez les compartiments de hachage selon des ratios de poids. Cette méthode est adaptée aux scénarios présentant des priorités métier différenciées (par exemple, la file d'attente 0 traite le trafic en temps réel et la file d'attente 1 gère les tâches en arrière-plan) ou des performances CPU mixtes.

    ethtool -X eth0 weight <queue 0 weight> <queue 1 weight> ...

    Dans l'exemple suivant, la file d'attente 0 reçoit 60 % et la file d'attente 1 reçoit 40 % :

    Remarque

    S'il y a quatre files d'attente au total, mais que vous ne définissez des poids que pour deux d'entre elles, la table d'indirection générera uniquement des mappages pour les files d'attente 0 et 1.

    ethtool -X eth0 weight 6 4

    image

  • Distribution partielle des files d'attente : À partir d'une file d'attente spécifiée, utilisez des files d'attente consécutives pour remplir les compartiments de hachage de manière cyclique. Cette option est recommandée pour diriger le trafic vers une plage CPU spécifique, telle qu'un nœud NUMA.

    ethtool -X eth0 start <start queue> equal <number of queues>

    Dans l'exemple ci-dessous, les files d'attente 2 à 41 (40 files d'attente à partir de la file d'attente 2) remplissent les compartiments de hachage :

    ethtool -X eth0 start 2 equal 40

    image

Utiliser watch pour observer la distribution du trafic

Après avoir activé le RSS personnalisé sur l'ENI, utilisez hping3 pour générer du trafic avec différentes caractéristiques et watch pour surveiller la distribution des interruptions des files d'attente, afin de vérifier si le trafic est bien réparti sur plusieurs cœurs comme prévu.

Prérequis

Achetez deux instances ECS avec les configurations suivantes :

  • Instance ECS émettrice (10.0.0.252) : Une instance sur laquelle hping3 est installé pour générer du trafic avec différentes caractéristiques.

  • Instance ECS réceptrice : Une instance dont le type prend en charge les files d'attente multiples pour les ENI, avec une ENI secondaire attachée (10.0.0.5) et le RSS personnalisé activé sur l'ENI secondaire eth1.

    Remarque
    • Cet exemple utilise quatre files d'attente pour les tests.

    • Pour éliminer l'impact du trafic de connexion SSH sur l'ENI principale, le RSS personnalisé est activé sur l'ENI secondaire eth1 pour les tests.

  • Connectivité réseau : Les deux instances ECS se trouvent dans le même groupe de sécurité et peuvent communiquer entre elles via le réseau interne.

Procédure

  1. Connectez-vous à l'instance ECS réceptrice, vérifiez la configuration RSS de l'ENI secondaire et confirmez la distribution de trafic attendue. Consultez la section Afficher la configuration RSS d'une ENI.

    image

  2. Connectez-vous à l'instance ECS émettrice et installez hping3.

    yum install -y hping3
  3. Sur l'instance ECS réceptrice, surveillez les compteurs de paquets des files d'attente en temps réel.

    watch -n 1 "ethtool -S eth1 | grep rx[0,1,2,3]_packets"

    Remplacez la configuration du numéro de file d'attente par la configuration réelle de l'ENI réceptrice.

  4. Connectez-vous à l'instance ECS émettrice et simulez différents modèles de trafic.

    • Scénario 1 : Envoyez 10 000 paquets SYN à haute vitesse vers l'adresse IP du récepteur avec des ports de destination aléatoires. Cela garantit que le hachage du trafic est dispersé et permet de vérifier l'équilibrage du hachage.

      sudo hping3 10.0.0.5 -S -a 10.0.0.252 --rand-dest -p 0 --baseport 10000 -c 10000 -i u100 -I eth0
      • rand-dest : Port de destination aléatoire

      • -p 0 : Utilisé conjointement avec rand-dest

      • --baseport 10000 : Valeur de départ pour le port source.

      • -c 10000 : Envoie 10 000 paquets

      • -i u100 : Spécifie un intervalle de 100 microsecondes entre les paquets pour un envoi à haute vitesse.

      • -I eth0 : Utilisé conjointement avec rand-dest pour spécifier l'interface réseau de l'émetteur

      Sur l'instance réceptrice, les compteurs de paquets des quatre files d'attente doivent augmenter de manière uniforme :

      image

    • Scénario 2 : Envoyez du trafic avec une adresse IP source et un port fixes. Ce test permet de vérifier si le même trafic est mappé sur la même file d'attente et de confirmer la cohérence du hachage.

      La commande suivante envoie 10 000 paquets TCP SYN vers la cible 10.0.0.5:80, avec l'IP source fixée sur 10.0.0.252 et le port source fixé sur 12345.

      sudo hping3 10.0.0.5 -S -p 80 -c 10000 -s 12345 -a 10.0.0.252 --keep -i u100
      • La valeur d'index de hachage est calculée en fonction du script RSS. Le trafic devrait être traité par la file d'attente 0 :

        image

      • Résultat d'observation réel sur l'instance ECS réceptrice (10.0.0.5) :

        image

  5. Si la distribution du trafic ne répond pas aux attentes (par exemple, si une file d'attente présente une charge significativement plus élevée), optimisez la configuration en ajustant la clé de hachage ou en configurant la table d'indirection.

Configurer et utiliser RSS dans DPDK

Le Data Plane Development Kit (DPDK) est un framework open source d'accélération du plan de données en mode utilisateur qui utilise des pilotes en mode utilisateur, la copie zéro et le mode d'interrogation pour atteindre un traitement des paquets proche de la vitesse de la ligne. Il convient aux domaines sensibles au débit et à la latence, tels que les clouds de télécommunications, la fintech et l'informatique en périphérie. Consultez la page Data Plane Development Kit (DPDK*).

Après avoir activé le RSS personnalisé sur l'ENI, vous pouvez utiliser testpmd et l3fwd dans DPDK pour tester et vérifier la distribution RSS.

Installer et configurer DPDK sur une instance ECS

Remarque
  • Si vous utilisez la fonctionnalité RSS personnalisé dans une application DPDK, la version de DPDK doit être 21,11 ou ultérieure.

  • Cette rubrique utilise une instance ecs.r9i.16xlarge (64 files d'attente) exécutant l'image Alibaba Cloud Linux 3.2104 LTS 64-bit comme exemple pour démontrer l'installation de la version 22.11.3 de DPDK.

  • Cet exemple utilise l'ENI principale eth0. Remplacez l'identifiant d'interface par eth1 ou eth2 pour modifier le RSS de l'ENI secondaire correspondante.

Étape 1 : Installer DPDK

Cliquez pour afficher les étapes d'exemple pour installer DPDK

  1. Mettez à jour le système et installez les outils de base.

    sudo yum update -y
    sudo yum install -y git wget gcc make kernel-devel-$(uname -r) numactl-devel python3 pciutils
  2. Installez les dépendances de DPDK.

    sudo yum install -y libpcap-devel meson ninja-build
  3. Configurez les pages énormes (huge pages).

    • DPDK contourne la pile de protocoles du noyau pour opérer directement sur l'ENI. Il utilise des pages énormes (généralement 2 Mo) au lieu de pages de 4 Ko pour réduire les échecs TLB et améliorer la vitesse d'accès à la mémoire.

    • L'allocation d'un trop grand nombre de pages énormes réduit la mémoire normale disponible pour le système d'exploitation. Cela peut entraîner l'échec d'autres applications ou services système. Une allocation excessive peut également empêcher la connectivité de l'instance.

    • Calculez le nombre requis de pages énormes en fonction des besoins en mémoire de votre application.

      Nombre de pages énormes = Mémoire de l'application / Taille de la page. La taille de page par défaut est de 2 Mo. Par exemple, 16 Go / 2 Mo = 8 192 pages.

    echo "vm.nr_hugepages = 8192" | sudo tee -a /etc/sysctl.conf
    sudo sysctl -p
  4. Créez et montez le répertoire des pages énormes.

    sudo mkdir -p /dev/hugepages
    sudo mount -t hugetlbfs hugetlbfs /dev/hugepages
  5. Téléchargez le code source de DPDK. Une connexion Internet est requise.

    cd ~
    wget https://fast.dpdk.org/rel/dpdk-22.11.3.tar.xz
    tar xf dpdk-22.11.3.tar.xz
    cd dpdk-stable-22.11.3
  6. Compilez DPDK.

    # Initialize the build directory and configure project options, specifying to build the l3fwd Layer 3 forwarding example.
    meson setup -Dexamples=l3fwd build
    cd build
    # Compile.
    ninja
    # Install the compiled files to the system directory.
    sudo ninja install
    # Update the system's shared library cache.
    sudo ldconfig

    Si vous rencontrez l'erreur missing python module: elftools illustrée dans la figure ci-dessous lors de la compilation,

    image

    Spécifiez votre version Python, installez pyelftools et recompilez :

    sudo /usr/bin/python3.8 -m pip install pyelftools

Étape 2 : Charger les modules du noyau

DPDK nécessite des modules du noyau tels que UIO ou VFIO pour l'accès aux périphériques en mode utilisateur. VFIO est préféré pour sa sécurité (il s'appuie sur IOMMU), tandis que UIO convient aux tests rapides. Cet exemple utilise VFIO.

  1. Activez IOMMU.

    VFIO s'appuie sur IOMMU pour une liaison sécurisée des périphériques en mode utilisateur et un mappage DMA.

    1. Ouvrez le fichier.

      sudo vim /etc/default/grub
    2. Appuyez sur i pour entrer en mode insertion. Ajoutez intel_iommu=on au paramètre GRUB_CMDLINE_LINUX . Enregistrez et fermez le fichier.

      Exemple de configuration modifiée :

      GRUB_TIMEOUT=1
      GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
      GRUB_DEFAULT=saved
      GRUB_DISABLE_SUBMENU=true
      GRUB_TERMINAL_OUTPUT="console"
      GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet idle=halt biosdevname=0 net.ifnames=0 console=tty0 console=ttyS0,115200n8 noibrs intel_iommu=on"
      GRUB_DISABLE_RECOVERY="true"
    3. Appliquez la configuration.

      sudo grub2-mkconfig -o /boot/grub2/grub.cfg
      [test@iZ2ze9h6rn          ~]$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
      Generating grub configuration file ...
      Found linux image: /boot/vmlinuz-4.19.91-27.4.al7.x86_64
      Found initrd image: /boot/initramfs-4.19.91-27.4.al7.x86_64.img
      Found linux image: /boot/vmlinuz-0-rescue-2cea6e3dd20d4251bf6880159559f2c9
      Found initrd image: /boot/initramfs-0-rescue-2cea6e3dd20d4251bf6880159559f2c9.img
      done
    4. Redémarrez l'instance et reconnectez-vous après son démarrage.

      reboot
      Avertissement

      L'opération de redémarrage arrête l'instance pendant une courte période et peut interrompre les services en cours d'exécution sur l'instance. Nous vous recommandons de redémarrer l'instance pendant les heures creuses.

  2. Installez les pilotes VFIO et VFIO-PCI.

    sudo modprobe vfio && \
    sudo modprobe vfio-pci
  3. Activez noiommu_mode.

    sudo bash -c 'echo 1 > /sys/module/vfio/parameters/enable_unsafe_noiommu_mode'

Étape 3 : Lier l'ENI au pilote DPDK

  1. Activer le RSS personnalisé sur l'ENI.

    Assurez-vous que le RSS personnalisé est activé pour l'ENI que DPDK va prendre en charge et que l'ENI a été rattachée pour que la modification prenne effet.

  2. Se connecter à une instance à l'aide de VNC.

  3. Affichez l'état de liaison du pilote de périphérique PCI. Par défaut, l'ENI est gérée par le noyau.

    dpdk-devbind.py --status

    image

    • Le périphérique 0000:00:05.0 est géré par le pilote du noyau virtio-pci et eth0 est actif.

    • Le périphérique peut être basculé vers vfio-pci pour une prise en charge en mode utilisateur par DPDK. Désactivez d'abord l'interface et détachez le pilote du noyau.

  4. Désactivez eth0.

    sudo ip link set dev eth0 down

    Si vous ignorez cette étape, la liaison à VFIO échoue :

    image

  5. Détachez le pilote du noyau et liez-le à VFIO.

    dpdk-devbind.py -b vfio-pci 0000:00:05.0

    Remplacez l'identifiant de périphérique PCI par celui que vous avez interrogé pour votre ENI.

    Remarque

    Pour reliaisonner le pilote du noyau, arrêtez l'application DPDK avec sudo pkill dpdk-app et exécutez dpdk-devbind.py -b virtio-pci 0000:00:05.0.

  6. Affichez à nouveau l'état de liaison du pilote de périphérique PCI. L'ENI devrait désormais être prise en charge par DPDK.

    Important

    Lorsque l'ENI est prise en charge par le pilote en mode utilisateur DPDK, le noyau ne la contrôle plus. Des commandes telles que ip a ne peuvent pas afficher ses informations.

    dpdk-devbind.py --status

    image

    Le périphérique 0000:00:05.0 est désormais lié à vfio-pci.

Configurer RSS à l'aide de testpmd

Testpmd est un outil de test DPDK permettant de vérifier les fonctionnalités du pilote ENI et de déboguer les applications du plan de données. Consultez Testpmd Runtime Functions.

Important

Les modifications apportées à la configuration ENI (nombre de files d'attente, règles RSS, table RETA) ne prennent effet qu'après le démarrage ou le redémarrage de la transmission des paquets.

  1. Se connecter à une instance via VNC.

  2. Démarrez l'outil de test de transmission de paquets DPDK testpmd.

    dpdk-testpmd -a 0000:00:05.0 --socket-mem 1024 -- -i --portmask=0x1 --rxq=64 --txq=64  --forward-mode=rxonly
    • -a 0000:00:05.0 : attache l'ENI à l'adresse PCI 0000:00:05.0 à DPDK. Exécutez dpdk-devbind.py --status pour trouver l'adresse PCI.

    • --socket-mem 1024 : pré-alloue 1 024 Mo de mémoire de pages géantes par nœud NUMA.

    • -i : démarre le mode de ligne de commande interactif pour ajuster dynamiquement la configuration et afficher les statistiques. Saisissez quit pour quitter.

    • --portmask=0x1 : active le masque de port 0x1 (binaire 0001), en utilisant uniquement la première ENI (adresse PCI 0000:00:05.0).

      • Chaque bit binaire de portmask correspond à un port (0x1 active le port 0, 0x3 active les ports 0 et 1).

      • Un seul périphérique (0000:00:05.0) étant attaché, son numéro de port DPDK est 0.

    • --rxq=64 / --txq=64 : définit le nombre de files d'attente RX et TX par port à 64 pour le traitement multi-files. Remplacez 64 par le nombre de files d'attente ENI réel.

    • --forward-mode=rxonly : mode réception uniquement (les paquets sont reçus et ignorés). Utilisé pour tester les performances de réception de l'ENI ou pour la capture de paquets.

  3. Accédez au mode interactif et interrogez la configuration RSS actuelle.

    • Interroger les informations de configuration de hachage : show port info <port_id>

      port_id : le port. Dans cet exemple, le port 0.

      Cliquez pour afficher l'exemple de sortie

      image

    • Interroger la clé de hachage : show port <port_id> rss-hash key

      image

    • Interroger la configuration de la table d'indirection : show port <port_id> rss reta <size> <mask0, mask1...>

      • size : le nombre d'entrées de la table d'indirection à interroger. La valeur est fixée à 128.

      • mask0, mask1 : les masques utilisés pour filtrer la plage d'index de hachage à afficher, spécifiés au format hexadécimal. Par exemple, mask0=0xff indique que les entrées pour les index de hachage 0 à 7 sont affichées.

        La taille de la table d'indirection est fixée à 128. Deux masques sont requis, chacun couvrant 64 blocs d'index. Exécutez show port 0 rss reta 128 (0xffffffffffffffff,0xffffffffffffffff) pour renvoyer les 128 mappages index-vers-file d'attente :

        Cliquez pour afficher l'exemple de sortie

        image

  4. Configurez RSS selon vos besoins.

    • Configurez une nouvelle clé de hachage.

      Générer une nouvelle clé aléatoire avec OpenSSL.

      port config <port_id> rss-hash-key (ipv4|ipv4-frag|\
                        ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|\
                        ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|\
                        ipv6-other|l2-payload|ipv6-ex|ipv6-tcp-ex|\
                        ipv6-udp-ex <string of hex digits \
                        (variable length, NIC dependent)>)

      Pour TCP sur IPv4, exécutez port config 0 rss-hash-key ipv4 6D5A56DA255B0EC24167253D43A38FB0D0CA2BCBAE7B30B477CB2DA38030F20C6A42B73BBEAC01FC pour configurer la clé de hachage et vérifier :

      image

    • Configurez la table d'indirection RSS pour mapper les valeurs de hachage aux files d'attente spécifiées.

      port config all rss reta <hash,queue>,<hash,queue>..

      Effectuez la configuration en fonction du nombre réel de files d'attente :

      • hash : l'index de hachage. La plage dépend de la taille de la table d'indirection (par exemple, 0-63 pour 64 entrées).

      • queue : le numéro de la file d'attente de réception cible.

Appliquer RSS dans l3fwd

Pour activer RSS dans une application DPDK, implémentez la configuration de la clé de hachage et de la table d'indirection dans votre code. L'exemple suivant utilise L3FWD.

L3FWD (Layer 3 Forwarding) est un exemple d'application DPDK qui illustre le routage de paquets basé sur IP haute performance utilisant le zéro copie et les pilotes en mode polling (PMD).

  1. Modifiez le code source L3FWD dans DPDK (examples/l3fwd/main.c).

    • Modifiez la section d'initialisation du port static struct rte_eth_conf port_conf dans l'exemple de code L3FWD.

      Cliquez pour afficher la modification du code

      #define RSS_HASH_KEY_LENGTH 	40
      #define RSS_RETA_SIZE 			128
      
      static uint8_t hash_key[RSS_HASH_KEY_LENGTH] = {
          0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
          0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
          0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
          0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
      };
      
      static struct rte_eth_conf port_conf = {
      	.rxmode = {
      		.mq_mode = RTE_ETH_MQ_RX_RSS,
      		.offloads = RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM,
      	},
      	.rx_adv_conf = {
      		.rss_conf = {
      			.rss_key = hash_key,
      			.rss_hf = RTE_ETH_RSS_IP,
      			.rss_key_len = RSS_HASH_KEY_LENGTH,
      		},
      	},
      	.txmode = {
      		.mq_mode = RTE_ETH_MQ_TX_NONE,
      	},
      };
    • Ajoutez des fonctions pour configurer la table d'indirection de hachage et la clé de hachage.

      Cliquez pour afficher le code ajouté

      /**
       * @brief Configure the RSS RETA (Redirection Table Array) for a given port.
       * 
       * @param port_id The ID of the port to configure.
       */
      
      void configure_rss_reta(uint16_t port_id) {
          struct rte_eth_rss_reta_entry64 reta_conf[RSS_RETA_SIZE / RTE_ETH_RETA_GROUP_SIZE];
          unsigned int i;
          uint16_t reta_size;
      	uint16_t nb_queues;
      	struct rte_eth_dev_info dev_info;
      
      	if (port_id >= RTE_MAX_ETHPORTS) {
              printf("port_id %d exceed max eth ports\n", port_id);
              return;
          }
      
          if (rte_eth_dev_info_get(port_id, &dev_info) != 0) {
      		printf("Failed to get device info for port %d\n", port_id);
      		return;
      	}
      
          reta_size = dev_info.reta_size;
          if (reta_size == 0) {
              printf("Device does not support RSS RETA configuration.\n");
              return;
          }
      
      	nb_queues = dev_info.nb_rx_queues;
      	if (nb_queues == 0) {
      		printf("port %d RX queues = 0\n", port_id);
      		return;
      	}
      
          // Initialize RETA table
          memset(reta_conf, 0, sizeof(reta_conf));
          for (i = 0; i < reta_size; i++) {
              reta_conf[i / RTE_ETH_RETA_GROUP_SIZE].reta[i % RTE_ETH_RETA_GROUP_SIZE] = (uint16_t)(i % nb_queues);
          }
      
          // Configure RETA table mask
          for (i = 0; i < reta_size; i += RTE_ETH_RETA_GROUP_SIZE) {
              reta_conf[i / RTE_ETH_RETA_GROUP_SIZE].mask = UINT64_MAX;
          }
      
      	// Update RSS RETA table to device
      	if (rte_eth_dev_rss_reta_update(port_id, reta_conf, reta_size) != 0) {
      		printf("Failed to update RSS RETA table for port %u\n", port_id);
      		return;
      	}
      }
      
      /**
       * @brief Configure the RSS hash key for a given port.
       * 
       * @param port_id The ID of the port to configure.
       */
      void configure_rss_hash_key(uint16_t port_id) {
          struct rte_eth_rss_conf rss_conf;
      
      	if (port_id >= RTE_MAX_ETHPORTS) {
              printf("port_id %d exceed max eth ports\n", port_id);
              return;
          }
      
          memset(&rss_conf, 0, sizeof(rss_conf));
          rss_conf.rss_key = hash_key;
          rss_conf.rss_key_len = sizeof(hash_key);
          
          // Update RSS hash key to device
          if (rte_eth_dev_rss_hash_update(port_id, &rss_conf) != 0) {
              printf("Failed to update RSS hash key for port %u\n", port_id);
      		return;
          }
      }
    • Après rte_eth_dev_start, appelez les nouvelles fonctions de configuration.

      Cliquez pour afficher le code d'appel dans main

      @@ -1472,12 +1576,15 @@ main(int argc, char **argv)
                      /* Start device */
      		ret = rte_eth_dev_start(portid);
      		if (ret < 0)
      			rte_exit(EXIT_FAILURE,
      				"rte_eth_dev_start: err=%d, port=%d\n",
      				ret, portid);
      				
      		configure_rss_reta(portid);
      		configure_rss_hash_key(portid);
  2. Recompilez L3FWD après avoir modifié le code source.

    cd ~/dpdk-stable-22.11.3/
    rm -rf build
    # Initialize the build directory and configure project options, specifying to build the l3fwd Layer 3 forwarding example.
    meson setup -Dexamples=l3fwd build
    cd build
    # Compile.
    ninja
    # Install the compiled files to the system directory.
    sudo ninja install
    # Update the system's shared library cache.
    sudo ldconfig
  3. Spécifiez les liaisons port-file-cœur et démarrez L3FWD.

    cd ~/dpdk-stable-22.11.3/build/examples
    ./dpdk-l3fwd --legacy-mem -a 0000:00:05.0 --socket-mem 1024 -- -p 0x1 --config="(PORT_ID, QUEUE_ID, LCORE_ID), (PORT_ID, QUEUE_ID, LCORE_ID), ..." --parse-ptype
    • --config : chaque triplet spécifie :

      • PORT_ID : l'ID du port (commence à 0).

      • QUEUE_ID : l'ID de la file d'attente de réception (commence à 0).

      • LCORE_ID : l'ID du cœur logique (commence à 0).

    • L'exemple suivant utilise deux cœurs et deux files d'attente :

      ./dpdk-l3fwd --legacy-mem -a 0000:00:05.0 --socket-mem 1024 -- -p 0x1 --config="(0,0,0),(0,1,1)"  --parse-ptype
      • Le premier triplet (0,0,0) : le cœur logique 0 (lcore0) traite la file d'attente 0 du port 0.

      • Le deuxième triplet (0,1,1) : le cœur logique 1 (lcore1) traite la file d'attente 1 du port 0.

      image

Utiliser le script RSS pour calculer un index de hachage

Utilisez ce script Python pour déterminer à quelle file d'attente de réception un paquet est mappé, en fonction de son quadruplet et de sa clé de hachage. Le résultat guide la configuration de la table d'indirection pour diriger des flux spécifiques vers des files d'attente désignées.

Cliquez pour afficher le contenu du script ali_ecs_rss_calc.py

#!/usr/bin/python

import sys
import argparse
import re
import ipaddress

prog_name = sys.argv[0]
USAGE_EXAMPLE = """
Usage example:
    Calculate the Toeplitz hash of a packet sent from 1.2.3.4 to 1.2.3.5 with a source and destination
    port of 7000:

    - The hash key argument is required because the virtio-net driver creates a random hash key for all your NICs.

    $ {prog_name} -t 1.2.3.4 -T 7000 -r 1.2.3.5 -R 7000 -k 77:d1:c9:34:a4:c9:bd:87:6e:35:dd:17:b2:e3:23:9e:39:6d:8a:93:2a:95:b4:72:3a:b3:7f:56:8e:de:b6:01:97:af:3b:2f:3a:70:e7:04
    
    - If you want to calculate the RSS value of a packet whose protocol is not TCP or UDP, do not specify
      the source and destination ports. The script will calculate the hash value based on only the IP addresses.
      
    $ {prog_name} -t 1.2.3.4 -r 1.2.3.5 -k 77:d1:c9:34:a4:c9:bd:87:6e:35:dd:17:b2:e3:23:9e:39:6d:8a:93:2a:95:b4:72:3a:b3:7f:56:8e:de:b6:01:97:af:3b:2f:3a:70:e7:04
    
    - Use "--ipv6" to calculate the RSS value for IPv6 packets.
    
    $ {prog_name} -t 2001:250:250:250:250:250:250:1 -T 7000 -r 2001:250:250:250:250:250:250:2 -R 7000 -k 77:d1:c9:34:a4:c9:bd:87:6e:35:dd:17:b2:e3:23:9e:39:6d:8a:93:2a:95:b4:72:3a:b3:7f:56:8e:de:b6:01:97:af:3b:2f:3a:70:e7:04 --ipv6

    Note: Linux kernel 5.9 or later is required for hash function and key configuration support.
    
    Also, Linux kernels older than ANCK 5.10-018 had a bug where the default hash key shown by ethtool was not 
    the same as the one used by the device before any RSS configuration was manually changed. The script will print the
    correct hash value in this case if you do not specify the hash key during calculation.
""".format(prog_name = prog_name)

# The default key on instances for old alinux kernel(< ANCK 5.10-018) should be as below, not the one you get from "ethtool -x <nic_name>".
RSS_DEFAULT_KEY = [
	0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,
	0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,
	0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
	0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,
	0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA,
]
# The default key on instances for new alinux kernel(>= ANCK 5.10-018) is randomly generated.

TOEPLITZ_KEY_SIZE = 128
BITS_IN_BYTE = 8

def circular_shift_key_one_left(key):
    """Performs a cyclic left shift of the entire key.
    To cyclically shift all 40 bytes, the function
    shifts bits between adjacent bytes one at a time."""

    l = len(key)
    return [ ((key[i] << 1) & 0xff) | ((key[(i + 1) % l] & 0x80) >> 7) for i in range(0, l) ]

def or_32msb_bits_of_key(key):
    return (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | key[3]

def calculate_hash(rx_ip, rx_port, tx_ip, tx_port, initial_value, key):
    """Calculates the Toeplitz hash based on the provided parameters.
    Note: This implementation is specific to ENA and may not be
    compatible with the standard Toeplitz implementation."""

    hash_result = initial_value
    input_bytes = list()
    input_bytes += tx_ip + rx_ip + tx_port + rx_port

    for input_byte in input_bytes:
        for i in range(BITS_IN_BYTE):
            # is the (8 - i -1) bit set
            if (input_byte & (1 << (BITS_IN_BYTE - i - 1))):
                hash_result ^= or_32msb_bits_of_key(key)

            key = circular_shift_key_one_left(key)

    return hash_result

def ipv4_addr_type(str):
    """An argparse type function that transforms an
    IPv4 string into a list of integers."""
    if not re.match(r"^([0-9]{1,3}\.){3}[0-9]{1,3}$", str):
        raise argparse.ArgumentTypeError("The IP address must be in the format 1.2.3.4.")

    return [int(octet) for octet in str.split('.')]

def ipv6_addr_type(str):
    """An argparse type function that transforms an
    IPv6 string into a list of integers."""
    
    try:
        ip_str = ipaddress.IPv6Address(unicode(str))
    except ValueError as e:
        raise argparse.ArgumentTypeError("Invalid IPv6 address format: %s" % e)
    
    parts = ip_str.exploded.split(':')
    try:
        bytes_list = [int(part, 16) for part in parts]
        bytes_list = [(byte >> 8, byte & 0xff) for byte in bytes_list]
    except ValueError as e:
        raise argparse.ArgumentTypeError("Invalid IPv6 address format: %s" % e)
    
    return [item for sublist in bytes_list for item in sublist]

def toeplitz_key_type(str):
    """An argparse type function that transforms a
    Toeplitz key string into a list of hexadecimal values."""
    if not re.match(r"^([0-9a-zA-Z]{1,2}:){39}[0-9a-zA-Z]{1,2}$", str):
        raise argparse.ArgumentTypeError("The Toeplitz key format is invalid. It must be 40 hexadecimal values delimited by colons.")

    return [int(key_elem, 16) for key_elem in str.split(':')]

def main():

    parser = argparse.ArgumentParser(description='virtio-net Toeplitz hash calculator',
                                     formatter_class=argparse.RawDescriptionHelpFormatter,
                                     epilog=USAGE_EXAMPLE)

    parser.add_argument('-r', '--rx-ip', help='Receiving side IP', dest='rx_ip', nargs='?',
                        required=True, type=str)
    parser.add_argument('-R', '--rx-port', help='Receiving side port', dest='rx_port', nargs='?', type=int)
    parser.add_argument('-t', '--tx-ip', help='Transmitting side IP', dest='tx_ip', nargs='?', 
                        required=True, type=str)
    parser.add_argument('-T', '--tx-port', help='Transmitting side port', dest='tx_port', nargs='?', type=int)
    parser.add_argument('-k', '--toeplitz-key',
                        help='The Toeplitz key (only on instances that support changing it)',
                        dest='toeplitz_key', nargs='?', required=True, type=toeplitz_key_type)
    parser.add_argument('-i', '--ipv6',  action='store_true', help='Use IPv6 address type for IP arguments')

    args = parser.parse_args()

    if args.ipv6:
        rx_ip   = ipv6_addr_type(args.rx_ip)
        tx_ip   = ipv6_addr_type(args.tx_ip)
    else:
        rx_ip   = ipv4_addr_type(args.rx_ip)
        tx_ip   = ipv4_addr_type(args.tx_ip)
    
    if args.rx_port and args.tx_port:
        # "break" port number into two byte representation
        rx_port = [(args.rx_port & 0xff00) >> 8, args.rx_port & 0x00ff]
        tx_port = [(args.tx_port & 0xff00) >> 8, args.tx_port & 0x00ff]
    else:
        rx_port = tx_port = []
    
    key = args.toeplitz_key

    # calculate the hash with an initial value of 0
    hash = calculate_hash(rx_ip, rx_port, tx_ip, tx_port, 0, key)
    rss_table_entry_128 = hash % 128
    rss_table_entry_256 = hash % 256

    if args.ipv6:
        print("Sending traffic from [{}]:{} to [{}]:{}".format(args.tx_ip, args.tx_port, args.rx_ip, args.rx_port))
    else:
        print("Sending traffic from {}:{} to {}:{}".format(args.tx_ip, args.tx_port, args.rx_ip, args.rx_port))
    print("""The hash is calculated over the following fields:
    Source IP address
    Destination IP address""")
    if args.rx_port and args.tx_port:
        print("""    Source port
    Destination port""")
    print("Should result in the hash for all drivers:".ljust(50) + "{}".format(hex(hash)))
    print("RSS table entry (total length 128):".ljust(50) + "{}".format(rss_table_entry_128))
    print("RSS table entry (total length 256):".ljust(50) + "{}".format(rss_table_entry_256))
    return

if __name__ == '__main__':
    main()

Cliquez pour afficher l'utilisation du script

Affichez l'utilisation du script : python ali_ecs_rss_calc.py -h.

image

L'exemple suivant utilise la configuration RSS d'une ENI avec 64 files d'attente :

image

Calculez la valeur de hachage RSS à l'aide du script avec les informations de quintuplet suivantes (modifiez les valeurs si nécessaire).

  • Adresse IP de destination (-r) : 10.0.0.1, qui est l'adresse IP de l'ENI de l'instance réceptrice configurée avec RSS.

  • Adresse IP source (-t) : 10.0.0.251, qui est l'adresse IP de l'ENI de l'expéditeur.

  • Port de destination (-R) : 26000

  • Port source (-T) : 18042

  • Clé de hachage : obtenez-la à partir de la configuration de la table d'indirection RSS.

python ali_ecs_rss_calc.py -r 10.0.0.1 -t 10.0.0.251 -R 26000 -T 18042 -k 69:e8:7c:56:bf:03:9f:63:d7:c5:e5:96:b3:00:36:93:02:8c:d2:8f:cc:a9:00:65:fd:c8:94:71:5f:fd:c8:de:7a:30:a9:73:b3:33:0c:c6

Le script calcule le hachage à l'aide de l'algorithme toeplitz. Dans le résultat ci-dessous, le système utilise une longueur de table d'indirection de 128. Un index de hachage de 117 signifie que le paquet est mappé à la file d'attente à l'index 117.

image

Consultez la table d'indirection : l'index 117 est mappé à la file d'attente 53, donc les paquets sont traités par la file d'attente 53.

image