Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Nios II 7.2 IDE
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
Волощенко
Всем привет.
Есть вопрос к структуре, которая сама объединяет другие структуры. А точнее, к выравниванию полей между структурами, при таком объединении.
Вот, например, две структуры, Ethernet-заголовок и ARP-заголовок:
typedef struct ether_header { //14 bytes
u_char ether_dhost[6];
u_char ether_shost[6];
u_short ether_type;
} ETHERHDR;


typedef struct ether_arp { //28 bytes
u_short arp_hrd;
u_short arp_pro;
u_char arp_hln;
u_char arp_pln;
u_short arp_op;
u_char arp_sha[6];
u_long arp_spa;
u_char arp_tha[6];
u_long arp_tpa;
} ETHERARP;


Эти структуры объединяются в структуре, условно названной sss:

struct ARPFRAME {
ETHERHDR eth_hdr;
ETHERARP eth_arp;
}sss;


Я ожидаю, что поля в sss идут без вставок, но на границе между eth_hdr и eth_arp появилась ненужная вставка из 2-х байт. Это видно, если прогнать следующий короткий тест:

ps= (u_char*) &sss; printf("ffm=%04x\n", ps-pd); pd=ps;
ps= (u_char*) &sss.eth_hdr.ether_dhost; printf("ether_dhost=%04x\n", ps-pd);
ps= (u_char*) &sss.eth_hdr.ether_shost; printf("ether_shost=%04x\n", ps-pd);
ps= (u_char*) &sss.eth_hdr.ether_type; printf("ether_type =%04x\n", ps-pd);

ps= (u_char*) &sss.eth_arp.arp_hrd; printf("arp_hrd =%04x\n", ps-pd);
ps= (u_char*) &sss.eth_arp.arp_pro; printf("arp_pro =%04x\n", ps-pd);
ps= (u_char*) &sss.eth_arp.arp_hln; printf("arp_hln =%04x\n", ps-pd);
ps= (u_char*) &sss.eth_arp.arp_pln; printf("arp_pln =%04x\n", ps-pd);
ps= (u_char*) &sss.eth_arp.arp_op; printf("arp_op =%04x\n", ps-pd);
ps= (u_char*) &sss.eth_arp.arp_sha; printf("arp_sha =%04x\n", ps-pd);
ps= (u_char*) &sss.eth_arp.arp_spa; printf("arp_spa =%04x\n", ps-pd);
ps= (u_char*) &sss.eth_arp.arp_tha; printf("arp_tha =%04x\n", ps-pd);
ps= (u_char*) &sss.eth_arp.arp_tpa; printf("arp_pln =%04x\n", ps-pd);

В результате на консоль выводится:
ffm=05cc
ether_dhost=0000
ether_shost=0006
ether_type =000c
arp_hrd =0010

arp_pro =0012
arp_hln =0014
arp_pln =0015
arp_op =0016
arp_sha =0018
arp_spa =0020
arp_tha =0024
arp_pln =002c

Где явно видно, что на стыке между полями ether_type и arp_hrd четыре байта, а должно быть два, т.к. u_short ether_type имеет 2 байта.

Теперь вопрос: Как от этого избавиться, наверное, нужны дополнительные опции? Где их ставить?
В общем пока ступор

Если кто-то интересуется, то в атаче коды с подобными структурами и функциями для Ethernet-приложений для NiosII под LAN91C111 из далекой Германии, а точнее из Ethernut_de.
Postoroniy_V
а если так?
Код
#define PACKED      __attribute__((__packed__))

typedef struct ether_header {   //14 bytes
    u_char  ether_dhost[6];    
    u_char  ether_shost[6];    
    u_short ether_type;        
} ETHERHDR PACKED;

typedef struct ether_arp {   //28 bytes
    u_short arp_hrd;    
    u_short arp_pro;    
    u_char  arp_hln;    
    u_char  arp_pln;    
    u_short arp_op;    
    u_char arp_sha[6];
    u_long arp_spa;    
    u_char arp_tha[6];
    u_long arp_tpa;    
} ETHERARP PACKED;


struct ARPFRAME {
    ETHERHDR eth_hdr;
    ETHERARP eth_arp;
    }sss PACKED;


http://grok2.tripod.com/structure_packing.html
может и не сработать конечно, я не пробовал, без typedef попробуйте
vadimuzzz
скорее всего, это фича gcc. по умолчанию он будет раскладывать поля по адресам "удобным" для целевой архитектуры (для ниос - кратно 4-м). чтобы сделать выравнивание полей по 1 байту понадобится "__attribute__ ((__packed__))".
или что-то типа такого:

#pragma pack(push, 1)
struct MyStruct
{
double dbl;
int i;
long long lng;
};
#pragma pack(pop)

упс, опередили smile.gif
Волощенко
к Postoroniy_V
к vadimuzzz

Большое спасибо за помощь!!!
Из всего предложенного прошел только один вариант, который описан в ссылке от Postoroniy_V, т.е. так:
typedef struct ether_header { //14 bytes
u_char ether_dhost[6] __attribute__((__packed__));
u_char ether_shost[6] __attribute__((__packed__));
u_short ether_type __attribute__((__packed__));
} ETHERHDR;

typedef struct ether_arp { //28 bytes
u_short arp_hrd __attribute__((__packed__));
u_short arp_pro __attribute__((__packed__));
u_char arp_hln __attribute__((__packed__));
u_char arp_pln __attribute__((__packed__));
u_short arp_op __attribute__((__packed__));
u_char arp_sha[6] __attribute__((__packed__));
u_long arp_spa __attribute__((__packed__));
u_char arp_tha[6] __attribute__((__packed__));
u_long arp_tpa __attribute__((__packed__));
} ETHERARP;

он выдает по тесту следующее, т.е. все уже нормально:
ffm=05d0
ether_dhost=0000
ether_shost=0006
ether_type =000c
arp_hrd =000e

arp_pro =0010
arp_hln =0012
arp_pln =0013
arp_op =0014
arp_sha =0016
arp_spa =001c
arp_tha =0020
arp_pln =0026

Я испытал все другие, предложенные Вами варианты в разных комбинациях, в том числе и с #pragma и без typedef, но, ни один из них не прошел. Похоже, надо после каждой составляющей в структуре писать __attribute__((__packed__))
Еще раз спасибо beer.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.