Chapitre 06
Anatomie d'une trame Profinet
Objectifs du chapitre
- Distinguer les trois classes de trafic Profinet — acyclique, cyclique temps réel (RT) et isochrone (IRT) — et comprendre pourquoi le RT circule en Ethernet brut, sans IP.
- Lire la structure d'une trame RT champ par champ : FrameID, données process, CycleCounter, DataStatus.
- Se servir du FrameID comme clé de lecture instantanée du type de trame.
- Capturer et disséquer le trafic Profinet avec
tshark— filtres BPF de couche 2 et filtres d'affichagepn_*.
1. Profinet : trois classes de trafic
Avant de plonger dans les octets, il faut voir Profinet comme une superposition de flux qui n'ont ni le même rôle, ni la même urgence, ni même la même façon de circuler sur le fil. On en distingue trois grandes familles.
- Le trafic acyclique — tout ce qui n'est pas rythmé : la découverte et le nommage des stations (DCP), l'établissement de la connexion applicative (Application Relation, via des appels RPC sur UDP), la lecture/écriture de paramètres, les alarmes. C'est le « hors-bande » : ça arrive quand il faut, pas à cadence fixe.
- Le trafic cyclique temps réel (RT) — l'échange d'entrées/sorties qui se répète comme un métronome, typiquement toutes les 1 à 4 ms (classes RT_CLASS_1/2). C'est le cœur du bus : le contrôleur envoie ses sorties, chaque device renvoie ses entrées, sans arrêt.
- Le trafic isochrone (IRT) — la variante RT_CLASS_3, planifiée à la microseconde près par les switches, réservée aux applications qui exigent une synchronisation dure (axes coordonnés, mouvement). On ne fait que la mentionner ici ; elle sort du cadre de ce cours.
Le point décisif pour le diagnostic : les trames RT ne sont pas des paquets IP.
Ce sont des trames Ethernet brutes, identifiées par l'EtherType 0x8892
(« PROFINET »). Pas d'en-tête IP, pas de port TCP/UDP : rien à router. Elles vivent uniquement en
couche 2, à l'intérieur du domaine de diffusion. C'est pour cela qu'un outil qui ne
regarde que l'IP est aveugle au temps réel — on y revient au §5.
Le trafic cyclique est vital : c'est lui qui maintient les E/S à jour. On l'observe volontiers (capture passive), mais on ne le perturbe jamais sur une installation en production. Ici on travaille sur banc de test : capture et dissection sans conséquence.
2. Structure d'une trame RT
Une trame RT cyclique est étonnamment simple une fois qu'on connaît ses champs. Après les deux adresses MAC et un éventuel tag VLAN, tout tient dans une charge utile Profinet encadrée par un FrameID en tête et une poignée d'octets d'état en queue.
0x8892 et les données : la charge utile Profinet suit immédiatement. Le tag 802.1Q
(pointillés) est optionnel mais quasi toujours présent en RT, car il porte la priorité. Les octets
de queue — CycleCounter, DataStatus, TransferStatus — disent si la donnée est fraîche
et valide.Passons les champs en revue :
- @MAC destination / @MAC source — les 12 octets d'adressage Ethernet classiques. En
cyclique, ce sont les MAC réelles des équipements (ex.
00:1b:1b:2a:10:20pour une ET 200SP) ; en DCP de découverte, la destination est souvent une adresse de multicast. - Tag 802.1Q (optionnel) — 4 octets qui insèrent l'identifiant de VLAN et surtout la priorité (champ PCP). Détaillé au §4.
- EtherType
0x8892— l'étiquette « ceci est du Profinet ». C'est sur elle qu'on filtre pour tout capturer d'un coup. - FrameID (2 octets) — la clé de lecture : il dit de quel type de trame il s'agit (§3).
- Données process (IO data) — la charge utile applicative : l'image des entrées ou des sorties, structurée selon la configuration matérielle (les modules de l'ET 200SP, par exemple).
- CycleCounter — un compteur incrémenté à chaque cycle ; il permet de détecter une trame manquée ou rejouée.
- DataStatus (1 octet) — le champ d'état le plus riche. Ses bits indiquent notamment
State (Run/Stop de l'AR), DataValid (les données sont exploitables), Primary/Backup
(rôle en redondance), et l'agrégat ProviderState / StationProblem. Un
DataStatusqui bascule est souvent le premier signe visible d'un défaut. - TransferStatus — dernier octet, en principe à 0 en RT_CLASS_1 nominal.
3. Le FrameID, clé de lecture
Le FrameID est le champ qu'on apprend à lire en premier, car il classe la trame
instantanément, avant même d'en décoder le contenu. Chaque plage de valeurs correspond à une
nature de trafic. Le tableau ci-dessous donne les grandes plages — les bornes exactes
varient selon les versions de la spécification, mais tshark les décode de toute façon pour
toi ; l'important est l'ordre de grandeur.
| Plage FrameID (hexa) | Classe / usage | Nature |
|---|---|---|
0x0100–0x7FFF | IRT / RT_CLASS_3 (isochrone) | cyclique planifié |
0x8000–0xBBFF | RT_CLASS_1/2 (E/S cycliques) | cyclique temps réel |
0xFC01 | Alarme basse priorité | acyclique |
0xFE01 | Alarme haute priorité | acyclique |
0xFEFC–0xFEFF | DCP (découverte / configuration) | acyclique |
0xFF00–0xFF43 | PTCP (synchronisation d'horloge) | acyclique / temps |
Concrètement, dès qu'on voit un FrameID 0x8000, on sait sans rien lire d'autre : c'est
une trame d'E/S cyclique, la respiration normale du bus. Un 0xFEFE ? Du
DCP — quelqu'un cherche ou nomme une station. Un 0xFE01 ? Une
alarme haute priorité vient de partir, il se passe quelque chose.
Retiens juste les préfixes hexa : 0x8xxx = E/S cycliques,
0xFC/0xFE01 = alarmes, 0xFEFx = DCP, 0xFFxx = synchro. Lire le
FrameID d'un coup d'œil te dit le type de trame avant même de la disséquer — c'est le réflexe
le plus rentable du chapitre.
4. VLAN & priorité : faire passer le RT d'abord
Dans un switch, quand plusieurs trames se présentent en même temps, il faut arbitrer. Profinet ne laisse pas le hasard décider : les trames RT portent un tag 802.1Q avec une priorité PCP élevée (couramment PCP = 6), ce qui les place dans une file de sortie prioritaire, devant le trafic « best-effort » (web, SNMP, ping…). C'est ce qui garantit que la cadence temps réel tient même quand le réseau est chargé.
Sur une capture, le tag se lit dans les champs vlan.id et vlan.priority :
$ tshark -r cell.pcap -Y pn_rt -T fields -e vlan.id -e vlan.priority -e pn_rt.frame_id # tag + FrameID
0 6 0x8000
0 6 0x8001
0 6 0x8000
Ici le VLAN vaut 0 (VLAN par défaut, ou « priority-tagged » : on ne se sert du tag que pour la priorité), mais la priorité 6 confirme qu'on regarde bien du trafic prioritaire temps réel.
5. Capturer avec tshark
Puisque le RT n'a pas d'IP, on filtre au niveau liaison. Le filtre BPF de capture le plus utile est tout simplement l'EtherType Profinet :
# Capturer TOUT le Profinet sur l'interface machine (couche 2)
sudo tshark -i eth0 -f 'ether proto 0x8892'
Le -f 'ether proto 0x8892' est un filtre de capture (BPF) : il travaille
sur le fil, avant tout décodage. Une fois les trames capturées (ou relues depuis un .pcap), on
affine avec les filtres d'affichage Profinet, la famille pn_* :
Filtres d'affichage tshark à connaître :
-Y pn_dcp— découverte / nommage (DCP).-Y pn_rt— l'enveloppe RT (toute trame0x8892temps réel).-Y pn_io— les échanges acycliques d'établissement de connexion (RPC).-Y pn_alarm— les alarmes basse/haute priorité.-Y pn_ptcp— la synchronisation d'horloge (PTCP).
Pour du diagnostic scriptable, on extrait des champs précis avec -T fields.
Par exemple, le FrameID, l'émetteur et le compteur de cycle de chaque trame RT :
$ tshark -r cell.pcap -Y pn_rt \
-T fields -e pn_rt.frame_id -e eth.src -e pn_rt.cycle_counter
0x8000 00:1b:1b:2a:10:20 14208
0x8001 00:1b:1b:2a:10:01 14210
0x8000 00:1b:1b:2a:10:20 14224
0x8000 00:1b:1b:2a:10:20 14240
0x8001 00:1b:1b:2a:10:01 14242
On lit tout de suite la conversation cyclique : l'ET 200SP …10:20 émet des trames
0x8000 (ses entrées → contrôleur), le CPU …10:01 émet des 0x8001
(ses sorties → device), et le cycle_counter avance régulièrement de trame en trame. Un saut
dans ce compteur signalerait des trames perdues.
On capture obligatoirement en couche 2. Le RT n'a pas d'adresse IP : un
filtre host 192.168.0.20 ne l'attrapera jamais, car il n'y a pas d'IP à matcher
dans la trame. Et rappelle-toi le piège WSL2 du chapitre 1 : derrière le NAT
par défaut, tu ne verras aucune trame 0x8892. Capture depuis l'edge Debian ou passe WSL2 en
mode miroir.
6. Un extrait décodé, et le démarrage d'une station
Pour voir tous les champs d'une trame, on demande la vue verbeuse avec -V.
Sur une trame RT cyclique, on retrouve la structure du §2 :
$ tshark -r cell.pcap -Y 'pn_rt && pn_rt.frame_id == 0x8000' -V -c 1
...
PROFINET Real-Time
FrameID: 0x8000 (RT_CLASS_1)
IOData
# image des entrées du device (octets process)
CycleCounter: 14208
DataStatus: 0x35
.... ...1 = State: Primary
.... ..0. = Redundancy: primary AR
.... .1.. = DataValid: valid
...1 .... = ProviderState: Run
..1. .... = StationProblem: normal
TransferStatus: 0
Le DataStatus: 0x35 se lit bit à bit : la station est en Primary, les données sont
valides, le fournisseur est en Run, pas de StationProblem. C'est l'état sain
qu'on veut voir sur toutes les trames cycliques.
Enfin, le démarrage d'une station illustre l'enchaînement des trois classes de trafic. Filtre large sur une capture prise au moment de la mise sous tension d'un device :
$ tshark -r start.pcap -Y 'pn_dcp || pn_io || pn_rt' -T fields \
-e frame.number -e pn_rt.frame_id -e eth.src -e _ws.col.info
1 0xfefe 00:1b:1b:2a:10:01 # DCP Identify (le contrôleur cherche la station)
2 0xfeff 00:1b:1b:2a:10:20 # DCP Ident Ok (la station répond)
3 0xfefd 00:1b:1b:2a:10:01 # DCP Set : Name-of-Station / IP
5 192.168.0.1 # Connect Request (RPC UDP 34964) : ouverture de l'AR
6 192.168.0.20 # Connect Response : IOCR négociés
9 0x8000 00:1b:1b:2a:10:20 # première trame cyclique : l'échange RT démarre
La séquence est toujours la même : DCP (on identifie et on nomme la station, on lui
donne son IP) → Connect / AR (via RPC sur UDP 34964, on négocie les relations de
communication et les IOCR) → échange cyclique (les FrameID 0x8xxx
commencent à défiler). Reconnaître ces trois temps dans une capture, c'est savoir où un démarrage
se bloque.
Côté TIA Portal, ce que tu vois ici a un nom. L'AR (Application Relation)
établie par le Connect correspond à la relation « le CPU pilote ce device ». Les IOCR
(IO Communication Relations) sont les canaux d'entrées et de sorties cycliques que tu configures
dans les propriétés du device (temps de cycle « Watchdog », modules d'E/S). Le FrameID 0x8000
capturé sur le fil est exactement l'IOCR d'entrée que TIA a alloué à cette station.
La famille pn_* de dissecteurs (pn_rt, pn_dcp, pn_io,
pn_alarm, pn_ptcp) est intégrée à Wireshark/tshark depuis longtemps : aucune
extension à installer. Si un champ ne s'affiche pas, vérifie l'orthographe du filtre avec
tshark -G fields | grep pn_rt.
Récapitulatif
- Profinet superpose trois classes : acyclique (DCP, Connect/AR par RPC, alarmes), cyclique RT (E/S toutes les 1–4 ms), et isochrone IRT.
- Les trames RT sont de l'Ethernet brut, EtherType
0x8892, sans IP → on capture en couche 2. - Structure RT :
@dest | @src | [VLAN 802.1Q] | 0x8892 | FrameID | IO data | CycleCounter | DataStatus | TransferStatus. Le DataStatus porte l'état (Run/Stop, DataValid, Primary/Backup, StationProblem). - Le FrameID classe la trame d'un coup d'œil :
0x8xxx= E/S cycliques,0xFC01/0xFE01= alarmes,0xFEFx= DCP,0xFFxx= PTCP. - Le RT est prioritaire (tag 802.1Q, PCP = 6) pour passer avant le best-effort dans les switches.
- Outillage :
tshark -f 'ether proto 0x8892'pour capturer ; filtres d'affichage-Y pn_dcp/pn_rt/pn_io/pn_alarm/pn_ptcp; extraction-T fields -e pn_rt.frame_id -e eth.src -e pn_rt.cycle_counter; vue complète-V. - Un démarrage se lit en trois temps : DCP → Connect/AR (RPC UDP 34964) → échange cyclique.
Exercices
Exercice 1 — Compter les types de trames
Tu as capturé le trafic Profinet dans cell.pcap. Compte combien de trames de chaque type
il contient : DCP, RT cyclique, et alarmes. Quelle(s) commande(s) utiliser ?
Voir la solution
On relit le fichier avec un filtre d'affichage par famille et on compte les lignes :
$ for f in pn_dcp pn_rt pn_alarm; do \
printf '%-9s ' "$f"; tshark -r cell.pcap -Y "$f" 2>/dev/null | wc -l; done
pn_dcp 4
pn_rt 1876
pn_alarm 0
Sans surprise, le cyclique domine largement (des milliers de trames pn_rt
pour quelques pn_dcp de découverte). Zéro alarme = bon signe, la cellule
tourne sans défaut. On aurait pu capturer directement du fil avec
sudo tshark -i eth0 -f 'ether proto 0x8892' -a duration:10 -w cell.pcap avant de compter.
Exercice 2 — Qui émet du cyclique ?
À partir de cell.pcap, dresse la liste des équipements qui émettent des trames RT
cycliques, avec le FrameID qu'ils utilisent. Autrement dit : quels eth.src pour quels
frame_id ?
Voir la solution
$ tshark -r cell.pcap -Y pn_rt \
-T fields -e pn_rt.frame_id -e eth.src | sort | uniq -c
938 0x8000 00:1b:1b:2a:10:20
938 0x8001 00:1b:1b:2a:10:01
Deux émetteurs cycliques : l'ET 200SP …10:20 pousse ses entrées
en 0x8000, le CPU …10:01 pousse ses sorties en
0x8001. Le nombre quasi identique de trames (938 chacune) confirme un échange
régulier et symétrique — un cycle par sens, sans perte visible. Si un device attendu
n'apparaît pas dans la liste, c'est qu'il n'échange pas de cyclique : connexion non établie, ou station
absente.
Exercice 3 — Classer une trame inconnue
On te donne une trame isolée. En vue verbeuse, tu relèves : vlan.priority = 6,
vlan.id = 0, pn_rt.frame_id = 0xFE01. À quelle classe de trafic cette trame
appartient-elle, et qu'est-ce que ça t'apprend ?
Voir la solution
On lit les indices dans l'ordre :
- Priorité 6 + tag 802.1Q → trame Profinet prioritaire, traitée avant le best-effort par les switches.
- FrameID
0xFE01→ d'après le tableau du §3, c'est une alarme haute priorité — donc du trafic acyclique, pas du cyclique d'E/S.
Conclusion : ce n'est pas une trame d'échange normal, c'est une alarme urgente émise par une station (défaut de module, retrait/insertion, diagnostic). On confirmerait avec :
$ tshark -r cell.pcap -Y 'pn_alarm' -V | grep -iE 'alarm|frame id'
Le réflexe FrameID paie : sans lire la charge utile, on sait déjà qu'il faut aller regarder ce qui cloche sur la station émettrice.