Discussion:
Request help to explain invalid alignment errors
weiliam.hong
2011-07-04 20:02:38 UTC
Permalink
Hi,

I am trying my hand with the fbt provider and need some help in the
explaining my observation results.

------------------------------------------------
#!/usr/sbin/dtrace -s

fbt::ill_input_short_v4:entry
{
ip = (ipha_t *)args[1];
printf("%u\n",(ip->ipha_src));
}
-------------------------------------------------

Running the script generates lines upon lines of :
dtrace: error on enabled probe ID 1 (ID 44145:
fbt:ip:ill_input_short_v4:entry): invalid alignment (0xffffff014a8ec90e)
in action #2 at DIF offset 12

However,no error is observed when I replace ipha_src with any of the
first 8 members of ipha_s (ip_version_and_hdr_length to ipha_hdr_checksum)

-------------------------------------------------

From mdb -k
::print -t ipha_t
ipha_t {
uint8_t ipha_version_and_hdr_length
uint8_t ipha_type_of_service
uint16_t ipha_length
uint16_t ipha_ident
uint16_t ipha_fragment_offset_and_flags
uint8_t ipha_ttl
uint8_t ipha_protocol
uint16_t ipha_hdr_checksum
ipaddr_t ipha_src
ipaddr_t ipha_dst
}
From source,

#define _IPADDR_T
typedef uint32_t ipaddr_t;
#endif

Running sizeof(ipha_t) gives 20, which I think checks out at
(8+8+16+16+16+8+8+16+32+32)/8
-------------------------------------------------------------

Any ideas to get ipha_src print out properly ?

Many thanks,
Wei Liam
Andrew Gabriel
2011-07-04 20:59:25 UTC
Permalink
I think this is because the ip header is not necessarily 32 bit aligned
at this point. This will depend on the NIC you're using, use of VLANs or
not, etc. The best you can hope for is 16 bit aligned, so all the
uint8_t and uint16_t items can be accessed OK, but not the uint32_t
(ipaddr_t) items.

In this case, ipha_src is an IP address which always in network byte
order at this point, so we can access each byte of it without
dereferencing a misaligned 32bit item by doing something like this...

#!/usr/sbin/dtrace -s

fbt::ill_input_short_v4:entry
{
ip = (ipha_t *)args[1];
printf("%d.%d.%d.%d\n",
*(char *)&ip->ipha_src,
*((char *)(&ip->ipha_src)+1),
*((char *)(&ip->ipha_src)+2),
*((char *)(&ip->ipha_src)+3));
}
Post by weiliam.hong
Hi,
I am trying my hand with the fbt provider and need some help in the
explaining my observation results.
------------------------------------------------
#!/usr/sbin/dtrace -s
fbt::ill_input_short_v4:entry
{
ip = (ipha_t *)args[1];
printf("%u\n",(ip->ipha_src));
}
-------------------------------------------------
fbt:ip:ill_input_short_v4:entry): invalid alignment
(0xffffff014a8ec90e) in action #2 at DIF offset 12
However, no error is observed when I replace ipha_src with any of the
first 8 members of ipha_s (ip_version_and_hdr_length to ipha_hdr_checksum)
-------------------------------------------------
From mdb -k
::print -t ipha_t
ipha_t {
uint8_t ipha_version_and_hdr_length
uint8_t ipha_type_of_service
uint16_t ipha_length
uint16_t ipha_ident
uint16_t ipha_fragment_offset_and_flags
uint8_t ipha_ttl
uint8_t ipha_protocol
uint16_t ipha_hdr_checksum
ipaddr_t ipha_src
ipaddr_t ipha_dst
}
From source,
#define _IPADDR_T
typedef uint32_t ipaddr_t;
#endif
Running sizeof(ipha_t) gives 20, which I think checks out at
(8+8+16+16+16+8+8+16+32+32)/8
-------------------------------------------------------------
Any ideas to get ipha_src print out properly ?
Many thanks,
Wei Liam
--
Andrew Gabriel
weiliam.hong
2011-07-05 02:39:04 UTC
Permalink
Thanks Andrew, it works. I understand your workaround but don't actually
know why the ip_header can be misaligned in the first place.

Regards,
WL
Post by Andrew Gabriel
I think this is because the ip header is not necessarily 32 bit
aligned at this point. This will depend on the NIC you're using, use
of VLANs or not, etc. The best you can hope for is 16 bit aligned, so
all the uint8_t and uint16_t items can be accessed OK, but not the
uint32_t (ipaddr_t) items.
In this case, ipha_src is an IP address which always in network byte
order at this point, so we can access each byte of it without
dereferencing a misaligned 32bit item by doing something like this...
#!/usr/sbin/dtrace -s
fbt::ill_input_short_v4:entry
{
ip = (ipha_t *)args[1];
printf("%d.%d.%d.%d\n",
*(char *)&ip->ipha_src,
*((char *)(&ip->ipha_src)+1),
*((char *)(&ip->ipha_src)+2),
*((char *)(&ip->ipha_src)+3));
}
Post by weiliam.hong
Hi,
I am trying my hand with the fbt provider and need some help in the
explaining my observation results.
------------------------------------------------
#!/usr/sbin/dtrace -s
fbt::ill_input_short_v4:entry
{
ip = (ipha_t *)args[1];
printf("%u\n",(ip->ipha_src));
}
-------------------------------------------------
fbt:ip:ill_input_short_v4:entry): invalid alignment
(0xffffff014a8ec90e) in action #2 at DIF offset 12
However, no error is observed when I replace ipha_src with any of the
first 8 members of ipha_s (ip_version_and_hdr_length to
ipha_hdr_checksum)
-------------------------------------------------
From mdb -k
::print -t ipha_t
ipha_t {
uint8_t ipha_version_and_hdr_length
uint8_t ipha_type_of_service
uint16_t ipha_length
uint16_t ipha_ident
uint16_t ipha_fragment_offset_and_flags
uint8_t ipha_ttl
uint8_t ipha_protocol
uint16_t ipha_hdr_checksum
ipaddr_t ipha_src
ipaddr_t ipha_dst
}
From source,
#define _IPADDR_T
typedef uint32_t ipaddr_t;
#endif
Running sizeof(ipha_t) gives 20, which I think checks out at
(8+8+16+16+16+8+8+16+32+32)/8
-------------------------------------------------------------
Any ideas to get ipha_src print out properly ?
Many thanks,
Wei Liam
Bill Sommerfeld
2011-07-05 05:51:59 UTC
Permalink
Post by weiliam.hong
Thanks Andrew, it works. I understand your workaround but don't actually
know why the ip_header can be misaligned in the first place.
An ip header is commonly located right after a 14-byte ethernet header.

Many devices allow you to insert a two-byte shim at the start of a
packet buffer (so the ethernet header is 2-byte aligned and the ip
header is 4-byte aligned), but some ethernet controllers require the
start of the packet buffer to be 4-byte aligned and thus misalign the ip
header.

- Bill

Loading...