Paquet ethernet et boutisme

a marqué ce sujet comme résolu.

Bonjour,

Je réalise un project embarqué et cette fois en C au lieu d’Ada où les problèmes de boutisme sont très bien gérés par le compilateur. Je travaille sur une STM32F7 (ARM M7) qui est donc en petit boutisme.

Je reçois un paquet UDP dont la charge utile est encodée en gros boutisme. Il faut donc que je "convertisse" ces données pour mon microcontrôleur… Seulement, sauf incompréhension de ma part, il me semblait que le boutisme ne s’appliquait qu’à l’échelle de l’octet (et que donc que l’ordre des bits était conservé). Or ici, en utilisant le debugger de mon microcontrôleur je remarque que lorsque que le premier octet de mon paquet est 0x21 (vérifié sur Wireshark) la valeur lue par le microcontrôleur est différente (je ne me souviens plus de cette valeur…) et j’ai beau essayer de faire un calcul savant pour essayer de retrouver la valeur je me perd de plus en plus rien ne fais sens aha.

En gros, en analysant la payload de mon message UDP avec le debugger (pour ceux qui connaissent : lorsque LwIP appel ma callback UDP, j’analyse la payload du pbuf) les valeurs n’ont rien a voir avec mon paquet sur Wireshark. Pourtant l’adresse IP, le port et la taille du paquet lus par LwIP sont corrects (la bibliothèque utilise ntohs).

Ma question est comment je fais pour lire ce tableau d’octets qui est encodé en gros boutisme ?

// Sur wireshark message comme par 0x21 0x08
uint8_t * message = pbuf->payload; // Les valeurs de message n'ont aucun sens !!
// message[0] /= 0x21 !!!

Merci pour votre aide :)

+1 -0

Sans plus de contexte, on ne peut rien te dire.
Oui le boutisme agit au niveau des octets d’un mot et pas au niveau des bits. Donc tu devrais retrouver au moins tes valeurs, pas forcément dans le bon ordre. Le problème est certainement ailleurs.

UDP n’aillant pas de système garantissant l’intégrité des paquets, je conseillerais de remplacer le STM32F7 par un ordinateur (un autre, ou le même si tu as deux cartes réseaux) avec Wireshark afin de t’assurer que tu reçois bien ce que tu devrais recevoir. Ça te permet de ne pas remettre en cause le câble ou la carte réseau du PC émetteur.
Aussi, tu peux vérifier l’intégrité de ton paquet avec la somme de contrôle d’UDP.

Ton problème vient peut-être de ton utilisation de LwIP, ou d’un segment fault quelque part qui ré-écrit sur ton paquet.


Note: Regarde du coté de <cc.h> que tu importes et qui devrait définir la bonne entête.
Mais je répète, ça ne devrait pas être le problème. De 1, car tu devrais avoir les bonnes valeurs (pas forcément le bon ordre), de 2 car LwIP ne devrait rien faire (c’est-à-toi de gérer l’ordre des octets, LwIP laisse en Network-bytes-order) et de 3 car, il me semble, que pour l’instant tu n’as qu’un tableau d’octets. Le boutisme n’a pas de sens dans ce contexte, le boutisme c’est sur l’ordre des octets d’un mot.

Aussi, si jamais tu as un problème de boutisme, il existe les fonctions htonl htons, … pour changer de boutisme.

+1 -0

Bon je suis bien embêté dans ce cas…

Comme indiqué dans mon message je vois mon paquet sur wireshark et il est correct. LwIP arrive à extraire les bonnes informations des headers (checksum IP et UDP ok, j’ai également les bonnes adresses MAC, IPs, ports et longueur de valides).

Voici le code. Là où j’initialise le receveur:

static struct udp_pcb * udp_receiver;
osMessageQId messageQueueHandle;
    
void udp_initialize_receiver(void)
{
    udp_receiver = udp_new();
    
    if (udp_receiver != NULL)
    {
        if (udp_bind(udp_receiver, IP_ADDR_ANY, PDS_HOST_COMMAND_PORT) == ERR_OK)
        {
            udp_recv(udp_receiver, udp_receive_callback, NULL);
        }
        else
        {
#ifdef CONFIGURATION_DEBUG
            printf("[upd_initialize_receiver] failed to bind udp_receiver\n");
#endif
            udp_remove(udp_receiver);
        }
    }
    else
    {
#ifdef CONFIGURATION_DEBUG
        printf("[upd_initialize_receiver] failed to initialize udp_receiver\n");
#endif
    }
}

Et la callback:

void udp_receive_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, uint16_t port)
{
    if (p != NULL)
    {
        uint8_t * data = malloc(p->len);
        if (data != NULL)
        {
            memcpy(data, p->payload, p->len);
            if (osMessagePut(messageQueueHandle, data, 0) != osOK)
            {
#if CONFIGURATION_DEBUG
                printf("[udp_receive_callback] message queue is full\n");
#endif
            }
        }
        else
        {
#if CONFIGURATION_DEBUG
            printf("[udp_receive_callback] fail to malloc data\n");
#endif
        }
        p_free(p);
    }
}

Avec le debugger je break au niveau du malloc (qui à terme disparaîtra pour mettre directement que pbuf dans la queue). Les données d’entrée de la fonction sont bonnes, adresse IP ok, port OK. Sur mon réseau je n’ai qu’un seul message, donc c’est que la board l’a bien reçu (je le vois avec un PC branché sur un switch avec le port mirroring d’activé).

Et pourtant malgré tout ça, p->payload ne ressemble pas du tout à ce que vois sur wireshark… pour info je caste p->payload en uint8_t[12] avec le debugger, 12 étant la valeur, correcte, de p->len.

Ça ferait ça si le connecteur était branché à l’envers (si c’est possible …)

Alors, il me semble que la dissymétrie des broches d’un port Ethernet empêcherait que ça marche.

Par-contre, ce qui est possible c’est de se trompé entre câbles Ethernet croisés / droits. À ma connaissance, ça devrait empêcher toute communication (comme mettre un port à l’envers). Cependant, je n’ai pas connu le monde où les cartes réseaux n’inversaient pas l’ordre des broches lorsqu’elles rencontre se problème, donc je ne suis pas certain des conséquences. Il est tout à fait possible que dans le cas d’un microcontrôleur, l’inversion automatique soient optionnels.

Juste pour être sûr, tu utilises bien un câble croisé ?
Je ne vois rien dans ton code qui semble anormal. :/ Je ne suis pas un expert en lwIP par-contre.

+1 -0

tout est correct tel que vu par wireshark. Technique de capture te permet de retrouver des entêtes correctes, c’est la charge utile qui est incorrecte.
Il y a donc un problème au niveau la mise en oeuvre de de LwIP.
Plus précisément, il est probavle que la technique pour récupérer la charge utile ne fonctionne pas correctement.

+0 -0

Dans ma dernière édition (que je n’ai manifestement pas envoyé).

Je posais la question s’il y avait plusieurs paquets envoyés ou un seul.
En effet, la problématique du cache CPU ou mémoire en fonction d’où est enregistré le pbuffer pourrait jouer dans ce cas.

Aussi, il y a la fonction pbuf_take qui pourrait être intéressant d’étudier.

+0 -0

Juste pour être sûr, tu utilises bien un câble croisé ?

Non, j’utilise le même câble pour d’autre communication sans soucis (je travaille sur un système avec plusieurs microcontrôleur).

Je posais la question s’il y avait plusieurs paquets envoyés ou un seul.

Un seul paquet. Les caches sont désactivés pour le moment sur le CPU.

Je ne suis pas un expert en lwIP par-contre.

Moi non plus, je découvre ! Je pensais gagner du temps en l’utilisant, je commence à douter (en vrai si, j’utilise l’ARP et le ping, bien que pas complexe c’est toujours rébarbatif de les ré-implémenter et ça été automatique avec LwIP, du plug and play ;) )

Il y a donc un problème au niveau la mise en oeuvre de de LwIP.

Ça fait partie de mes deux hypothèses :

  • LwIP a plein de paramètre pour configurer les tailles de mémoire, il faut que je m’y penche, peut-être que quelque chose ne va pas.
  • Ou alors le debugger interprète mal les données. J’utilise FreeRTOS avec LwIP et je trouve que le debugger se comporte bizarrement (GDB sous STMCubeIDE). Peut-être qu’en fait tout va bien, il faut que je vérifie.

Je creuse ça demain matin première heure une fois que j’ai le système sous la main. Je vous tiens au courant, j’espère vraiment trouver une solution !

Merci

Bon, il s’avère que je ne sais pas lire le contenu de cet object pbuf dans mon code.
En effet, dans ma fonction udp_receive_callback, j’ai fait un udp_send(pcb, p); et j’ai bien exactement le même message qui part de la STM32 avec les mêmes données. Donc les valeurs en mémoire sont… bonnes !

Pourquoi alors avec mon debugger ou avec mon code C je n’arrive pas a les récupérer ? Je suis en train de devenir fou aha.

Message complet (wireshark). La payload commence au 0x21 x03. 0x1B 0x58 et 0x1C 0x20 ce sont bien les bons ports UDP
Message complet (wireshark). La payload commence au 0x21 x03. 0x1B 0x58 et 0x1C 0x20 ce sont bien les bons ports UDP
Le PBUF
Le PBUF
+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte