Date: Sun, 14 Jul 2002 13:43:37 -0700 From: Luigi Rizzo <luigi@freebsd.org> To: current@freebsd.org Subject: Re: different packing of structs in kernel vs. userland ? Message-ID: <20020714134337.A78891@iguana.icir.org> In-Reply-To: <20020714203642.GD314@crow.dom2ip.de>; from tmoestl@gmx.net on Sun, Jul 14, 2002 at 10:36:42PM %2B0200 References: <20020714011810.A72236@iguana.icir.org> <20020714203642.GD314@crow.dom2ip.de>
next in thread | previous in thread | raw e-mail | index | archive | help
[i am deliberately not trimming the email in case someone wants to look at the context] i am a bit dubious about your explaination -- it also does not explain why the person reporting this problem "fixed" that by swapping "timestamp" and "next_rule" in the structure cheers luigi On Sun, Jul 14, 2002 at 10:36:42PM +0200, Thomas Moestl wrote: > On Sun, 2002/07/14 at 01:18:10 -0700, Luigi Rizzo wrote: > > Hi, > > the following message seems to suggest that the compiler > > (the way it is invoked) packs structures differently > > when building the kernel and userland. > > > > The stize of the structure in question is computed > > by both kernel and userland app using sizeof(), > > so there is no assumption on the size of its members, > > so i believe the only possibility of a mismatch is > > the one above. > > > > Any ideas ? > > (Disclaimer: my solution below is untested, so it may all be bogus) > > No, you are not accounting for "external" structure padding. Take a > look: > > struct ip_fw { > struct ip_fw *next; /* linked list of rules */ > u_int16_t act_ofs; /* offset of action in 32-bit units */ > u_int16_t cmd_len; /* # of 32-bit words in cmd */ > u_int16_t rulenum; /* rule number */ > u_int16_t _pad; /* padding */ > > /* These fields are present in all rules. */ > u_int64_t pcnt; /* Packet counter */ > u_int64_t bcnt; /* Byte counter */ > u_int32_t timestamp; /* tv_sec of last match */ > > struct ip_fw *next_rule; /* ptr to next rule */ > > ipfw_insn cmd[1]; /* storage for commands */ > }; > > On a 64-bit architecture, pointers are obviously 8 bytes in size; > structure members must or should be on natural borders, depending on > the architecture. > So, next_rule will not be on a natural border; 4 bytes of padding will > be inserted before it. With that, the total structure size would be > 52. > The compiler must account for the fact that an array of struct ip_fws > may be used. For obvious reasons, it can not just insert extra padding > in the array case; instead, the structure size must be chosen so that > in this situation, the first member will be on a natural border. > This results in an extra 4 bytes of "external" padding at the end, > after the member 'cmd'. > The macro you use to compute the size in the kernel is: > > #define RULESIZE(rule) (sizeof(struct ip_fw) + \ > ((struct ip_fw *)(rule))->cmd_len * 4 - 4) > > In the userland code, you start at &foo.cmd and append data > directly. This means that the padding will also be used to store > data, so the '- 4' (= sizeof(foo.cmd)) will not always be enough. The > following definition of RULESIZE (untested) should fix this: > > #define RULESIZE(rule) (offsetof(struct ip_fw, cmd) + \ > ((struct ip_fw *)(rule))->cmd_len * 4) > > It also removes the explicit 4 for sizeof(ipfw_insn). > > - thomas > > -- > Thomas Moestl <tmoestl@gmx.net> http://www.tu-bs.de/~y0015675/ > <tmm@FreeBSD.org> http://people.FreeBSD.org/~tmm/ > PGP fingerprint: 1C97 A604 2BD0 E492 51D0 9C0F 1FE6 4F1D 419C 776C To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020714134337.A78891>