Auteur Sujet: Option information-spécifique au vendeur (en C)  (Lu 1053 fois)

0 Membres et 1 Invité sur ce sujet

basilix

  • Abonné Orange Fibre
  • *
  • Messages: 671
Option information-spécifique au vendeur (en C)
« le: 11 mai 2025 à 19:22:51 »
Salut !

J'ai beaucoup de difficulté à implémenter les options DHCPv4 code 125 et DHCPv6 code 17 dans odhcpd.
J'en suis à ma énième réécriture. Le code doit réaliser une analyse syntaxique de lignes de configuration.
Cette option spécifique au vendeur encapsule des sous-options. Il faut s'assurer qu'une sous-option n'est
pas dupliquée pour un même vendeur.

Je me suis basé sur le format ci-dessous, inspiré par dnsmasq.

id,code,data

id,option4:code,aa:bb:cc:dd (format hexadécimal en IPv4)
id,code,aabbccddee (format hexa. en IPv6)
id,code,"AOS-Switch:Top:Tokyo,3ffe:501:ffff:100::abcd,aruba123" (format texte)


J'ai rencontré des difficultés sur les allocations mémoires et la recherche d'une option en parcourant les mémoires tampon.
odhcpd emploie blob et blobmsg de l'API libubox. J'ai abandonné l'idée d'employer cette API. Je ne parviens pas à saisir
comment cela pourrait s'imbriquer dans le code existant. Sinon, les données ont chacune leur propre occupation mémoire.
Avec méconnaissance j'ai essayé d'écrire deux ou trois algorithmes mais sans parvenir à un résultat probant. J'ai aussi
beaucoup sollicité ChatGPT pour étudier certaines possibilités. Je lui ai posé des questions. Pour finir, je lui ai demandé
d'intégrer l'option lui-même. Mais il n'a pas appliqué ou trouvé les algorithmes adéquats. Pour finir, j'ai choisi d'élaborer
une machine à états. Le souci c'est que j'ai une vingtaine d'états différents à implémenter. Cela me donne tellement
l'impression de rater le coche.  :-\

basilix

  • Abonné Orange Fibre
  • *
  • Messages: 671
Option information-spécifique au vendeur (en C)
« Réponse #1 le: 11 mai 2025 à 19:41:14 »
Voici les états (j'en ai peut-être oublié un ou deux) :

enum State {
      STATE_READ_ID,
      STATE_CHECK_ID,
      STATE_READ_CODE,
      STATE_SET_NAMESPACE,
      STATE_ALLOC_BUFFER,
      STATE_SEARCH_ID,
      STATE_SELECT_BUFFER,
      STATE_SKIP_DATA_LEN,
      STATE_SEARCH_CODE,
      STATE_READ_LEN,
      STATE_SKIP_DATA,

      STATE_SET_PTR,
      STATE_END_DATA,
      STATE_READ_DATA,
      STATE_SET_LEN,
      STATE_REALLOC_BUFFER,
      STATE_WRITE_ID,
      STATE_WRITE_CODE,
      STATE_WRITE_LEN,
      STATE_WRITE_DATA,
      STATE_WRITE_DATA_LEN,
      STATE_END_STR,
      STATE_DONE,
      STATE_ERROR
   };


Pourquoi une machine à états ? Je pensais que cela m'aurait aidé à parcourir la mémoire tampon à la recherche d'une option existante.

basilix

  • Abonné Orange Fibre
  • *
  • Messages: 671
Option information-spécifique au vendeur (en C)
« Réponse #2 le: 14 mai 2025 à 17:50:30 »
C'est stupéfiant, le nombre de possibilités qui apparaît avec des variantes. Même ChatGPT me propose des variantes d'algorithmes sur des déclinaisons.
Je suis bloqué (pas simple, ou « principe KISS ») mais je retrouve différentes parties de procédés lors de mes interactions avec l'IA. C'est pas Eurêka !

basilix

  • Abonné Orange Fibre
  • *
  • Messages: 671
Option information-spécifique au vendeur (en C)
« Réponse #3 le: 15 mai 2025 à 17:57:22 »
Voici un exemple de code généré par ChatGPT 4.1 et légèrement remanié (inexact, mais c'est pour se faire une idée).

typedef struct {
    uint8_t option_code; // code spécifique de l’option
    uint8_t option_len;
    uint8_t *data;
} Option;

typedef struct {
    // collections pour DHCPv4 et DHCPv6
    Option *options_v4;
    size_t nb_options_v4;
    Option *options_v6;
    size_t nb_options_v6;
} VendeurOptions;

typedef struct {
    uint32_t vendeur_id; // identifiant du vendeur
    VendeurOptions options;
} Vendeur;

// tableau ou liste de vendeurs
Vendeur *vendeurs;
size_t nb_vendeurs;

Moi : Combien ai-je de niveaux de pointeurs pour accéder à data en partant d'une liste de vendeurs ?
ChatGPT : Pour accéder à data en partant de la liste de vendeurs, vous traversez 5 niveaux de pointeurs.
Moi : Cinq niveaux de pointeurs dans le code précédent. N'est-ce pas trop difficile à gérer en C pour un débutant ?
ChatGPT : Pour un débutant, il vaut mieux éviter d'utiliser plusieurs niveaux de pointeurs dès le départ. Progressivement, on peut introduire ces concepts avec des exemples concrets et une compréhension claire de leur gestion.
Moi : Mon algorithme emploie cinq niveaux de pointeurs en C. Que dois-je penser ?
ChatGPT :  Avoir cinq niveaux de pointeurs en C est une situation qui doit attirer votre attention. Cela suggère une complexité potentiellement excessive, des risques accrus d’erreurs, et une difficulté de maintenance.
Il serait conseillé d’étudier si la conception peut être simplifiée pour améliorer la sécurité, la clarté et la performance de votre code.

basilix

  • Abonné Orange Fibre
  • *
  • Messages: 671
Option information-spécifique au vendeur (en C)
« Réponse #4 le: 15 mai 2025 à 18:05:03 »
Autre exemple de code généré par ChatGPT.

struct option_entry {
uint32_t vendor_id;
int protocol; // 4 for DHCPv4, 6 for DHCPv6
union {
uint8_t u8;
uint16_t u16;
} option_code;
size_t data_len;
uint8_t *data;
};

struct vendor_options {
option_entry *entries;
size_t count;
size_t capacity;
};

On peut passer par qsort() et trier la liste d'options par protocole, par vendeur et enfin par code option. Mais il faut ensuite compacter les données et autres champs dans la même mémoire tampon.

Je lui demande si c'est performant.

Citer
5. Est-ce coûteux ?

- Coût mémoire : vous n'avez qu'une seule allocation, ce qui est généralement efficace.
- Coût temps : vous faites une seule passe pour calculer la taille, puis une autre pour copier. Cela reste raisonnable.
- Accès : accéder aux options nécessite de parcourir le tampon en avançant selon la taille de chaque option, ce qui est acceptable si vous traitez tout en bloc.

---

6. Résumé et recommandations

- La solution consiste à allouer un tampon unique, puis à copier `option_entry` et leurs données dedans, en ajustant les pointeurs.
- Cela évite plusieurs allocations et peut améliorer la performance en cache.
- Cependant, cela complique la gestion (libération, accès), donc à utiliser si la performance ou la réduction de fragmentation est essentielle.

basilix

  • Abonné Orange Fibre
  • *
  • Messages: 671
Option information-spécifique au vendeur (en C)
« Réponse #5 le: 15 mai 2025 à 19:29:07 »
On peut simplement inverser le raisonnement sans trop complexifier.

Pré-allouer un tampon suffisamment large par protocole et réallouer si nécessaire.
Créer la liste de sous-options et réallouer si nécessaire pour ajouter de nouveaux emplacements.
Rechercher dans cette liste si la sous-option n'est pas un duplicata.
Ajouter la sous-option dans le tampon.
Actualiser le pointeur data de la structure option_entry pour qu'il pointe vers les données dans le tampon.
Libérer la mémoire allouée pour ces données initialement.

En conséquence, on libère la mémoire au fur et à mesure et l'accès reste transparent.

basilix

  • Abonné Orange Fibre
  • *
  • Messages: 671
Option information-spécifique au vendeur (en C)
« Réponse #6 le: 15 mai 2025 à 19:36:57 »
Re :

Il faudrait également ajouter un nouveau champ dans la structure vendor_options pour établir le lien avec les différents tampons vendeurs.

[19:48]

Le champ serait un pointeur vers une structure afin de spécifier comment partitionner le tampon « protocole » lors de l'envoi d'une instance
de l'option 125 ou 17. Il suffirait d'indiquer la taille totale des sous-options d'une option vendeur pour recopier la mémoire en bloc.

basilix

  • Abonné Orange Fibre
  • *
  • Messages: 671
Option information-spécifique au vendeur (en C)
« Réponse #7 le: 21 mai 2025 à 11:04:22 »
Plus de 700 lignes de codes pour implémenter ces deux options.

J'ai exploité au max. ChatGPT pour améliorer mon code en le soumettant à analyse (pour effectuer des vérifications ou corrections).

Citer
Votre code est globalement cohérent, bien organisé et la logique semble correcte pour l’analyse et la fabrication des options DHCPv4 et DHCPv6.

Citer
Votre algorithme semble bien pensé pour le traitement ciblé des options DHCPv4 125 et DHCPv6 17 avec une gestion structurée des données, une déduplication efficace, et une organisation par vendeur.

Le problème qui revient est la complexité de traitement.

Citer
Complexité de traitement : La logique de tri, de vérification des duplicatas et de calculs peut devenir complexe à maintenir. Il serait judicieux d'utiliser des structures de données efficaces
(par exemple, des tables de hachage) pour accélérer la recherche et la détection des duplicatas.


Citer
La logique pour calculer la longueur totale des options est complexe mais semble correcte.

Je n'aurais jamais cru que l'implémentation de « l'option spécifique au vendeur » aurait dépassé 100 lignes de code.

Il faut encore que je code deux ou trois trucs et faire des tests.

basilix

  • Abonné Orange Fibre
  • *
  • Messages: 671
Option information-spécifique au vendeur (en C)
« Réponse #8 le: 22 mai 2025 à 14:24:09 »
Finalement, cela ne va pas le faire. C'est trop complexe comme solution. On peut faire plus simple.

#define dhcpv6_for_each_option(start, end, otype, olen, odata)\
   for (uint8_t *_o = (uint8_t*)(start); _o + 4 <= (end) &&\
      ((otype) = _o[0] << 8 | _o[1]) && ((odata) = (void*)&_o[4]) &&\
      ((olen) = _o[2] << 8 | _o[3]) + (odata) <= (end); \
      _o += 4 + (_o[2] << 8 | _o[3]))


#define dhcpv4_for_each_option(start, end, opt)\
   for (opt = (struct dhcpv4_option*)(start); \
      &opt[1] <= (struct dhcpv4_option*)(end) && \
         &opt->data[opt->len] <= (end); \
      opt = (struct dhcpv4_option*)&opt->data[opt->len])


Ces deux macros définies dans odhcpd permettent de parcourir une liste d'options. C'est très bien pour vérifier qu'une nouvelle option n'est pas un duplicata.

basilix

  • Abonné Orange Fibre
  • *
  • Messages: 671
Option information-spécifique au vendeur (en C)
« Réponse #9 le: 24 mai 2025 à 08:28:43 »
Une liste chaînée pourrait convenir en étant manipulable avec libubox.

Cela réduit la complexité de l'implémentation de mon algorithme. On peut faire abstraction des allocations mémoires et définir des fonctions génériques.
Si une option est définie plusieurs fois dans la configuration on l'écrase à chaque fois dans le tampon. Sinon, on renvoie l'emplacement dans le tampon
où la stocker (dans les données) et on la recopie simplement. Si le tampon n'est pas suffisamment large on l'agrandit. Lorsque le tampon est devenu
trop large on le réduit. Pour l'envoi d'une option spécifique au vendeur on parcourt la liste chaînée correspondante et on duplique les tampons. Ouf !
« Modifié: 26 mai 2025 à 07:40:04 par basilix »

mirtouf

  • Abonné Bbox fibre
  • *
  • Messages: 1 368
  • Chelles (77)
    • L'antre de la bête
Option information-spécifique au vendeur (en C)
« Réponse #10 le: 27 mai 2025 à 13:32:33 »
Salut,

est-ce que cela fera l'objet d'un PR ?

basilix

  • Abonné Orange Fibre
  • *
  • Messages: 671
Option information-spécifique au vendeur (en C)
« Réponse #11 le: 27 mai 2025 à 15:39:52 »
Salut @mirtouf !

J'aurais bien aimé que mon code soit intégré dans odhcpd. Je n'ai pas encore tout implémenté (absence d'idée et lassitude). Mais je pense que c'est assez bien réalisé.
Je prévois d'échanger si possible avec des contributeurs ou développeurs OpenWrt. J'aurais bien aimé savoir si l'on pouvait également exploiter l'API OpenWrt « blob »
pour pouvoir implémenter cette option. Ce sera peut-être un point de blocage pour son intégration. Néanmoins, si mon code est fonctionnel je le publierais dans mon
dépôt GitHub. On peut ensuite l'intégrer sous forme de correctif via « un feed ». Il serait toutefois préférable de l'intégrer dans l'original pour faciliter les mises à niveau
de odhcpd. Actuellement, je n'ai jamais construit de feed. Par contre, je compile mes images OpenWrt personnalisées. Or pour intégrer un nouveau correctif il faut
appliquer tous les correctifs (notamment ceux d'un fork) dans un ordre spécifique et les adapter à chaque version de odhcpd (à cause d'une désynchronisation entre
les sources du dépôt officiel et ceux du fork, patch ne fonctionne pas). Je ne promets rien sur la qualité du code produit. J'ai encore des lacunes et certaines choses
me paraissent assez complexes pour m'échapper.