diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2007-04-10 21:22:35 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-25 22:26:21 -0700 |
commit | 2e07fa9cd3bac1e28cfe3131ed86b053afb02fc9 (patch) | |
tree | 177ad0c2cbbd60c25e54b35802219634c047aa08 /include | |
parent | b0e380b1d8a8e0aca215df97702f99815f05c094 (diff) | |
download | linux-stable-2e07fa9cd3bac1e28cfe3131ed86b053afb02fc9.tar.gz linux-stable-2e07fa9cd3bac1e28cfe3131ed86b053afb02fc9.tar.bz2 linux-stable-2e07fa9cd3bac1e28cfe3131ed86b053afb02fc9.zip |
[SK_BUFF]: Use offsets for skb->{mac,network,transport}_header on 64bit architectures
With this we save 8 bytes per network packet, leaving a 4 bytes hole to be used
in further shrinking work, likely with the offsetization of other pointers,
such as ->{data,tail,end}, at the cost of adds, that were minimized by the
usual practice of setting skb->{mac,nh,n}.raw to a local variable that is then
accessed multiple times in each function, it also is not more expensive than
before with regards to most of the handling of such headers, like setting one
of these headers to another (transport to network, etc), or subtracting, adding
to/from it, comparing them, etc.
Now we have this layout for sk_buff on a x86_64 machine:
[acme@mica net-2.6.22]$ pahole vmlinux sk_buff
struct sk_buff {
struct sk_buff * next; /* 0 8 */
struct sk_buff * prev; /* 8 8 */
struct rb_node rb; /* 16 24 */
struct sock * sk; /* 40 8 */
ktime_t tstamp; /* 48 8 */
struct net_device * dev; /* 56 8 */
/* --- cacheline 1 boundary (64 bytes) --- */
struct net_device * input_dev; /* 64 8 */
sk_buff_data_t transport_header; /* 72 4 */
sk_buff_data_t network_header; /* 76 4 */
sk_buff_data_t mac_header; /* 80 4 */
/* XXX 4 bytes hole, try to pack */
struct dst_entry * dst; /* 88 8 */
struct sec_path * sp; /* 96 8 */
char cb[48]; /* 104 48 */
/* cacheline 2 boundary (128 bytes) was 24 bytes ago*/
unsigned int len; /* 152 4 */
unsigned int data_len; /* 156 4 */
unsigned int mac_len; /* 160 4 */
union {
__wsum csum; /* 4 */
__u32 csum_offset; /* 4 */
}; /* 164 4 */
__u32 priority; /* 168 4 */
__u8 local_df:1; /* 172 1 */
__u8 cloned:1; /* 172 1 */
__u8 ip_summed:2; /* 172 1 */
__u8 nohdr:1; /* 172 1 */
__u8 nfctinfo:3; /* 172 1 */
__u8 pkt_type:3; /* 173 1 */
__u8 fclone:2; /* 173 1 */
__u8 ipvs_property:1; /* 173 1 */
/* XXX 2 bits hole, try to pack */
__be16 protocol; /* 174 2 */
void (*destructor)(struct sk_buff *); /* 176 8 */
struct nf_conntrack * nfct; /* 184 8 */
/* --- cacheline 3 boundary (192 bytes) --- */
struct sk_buff * nfct_reasm; /* 192 8 */
struct nf_bridge_info *nf_bridge; /* 200 8 */
__u16 tc_index; /* 208 2 */
__u16 tc_verd; /* 210 2 */
dma_cookie_t dma_cookie; /* 212 4 */
__u32 secmark; /* 216 4 */
__u32 mark; /* 220 4 */
unsigned int truesize; /* 224 4 */
atomic_t users; /* 228 4 */
unsigned char * head; /* 232 8 */
unsigned char * data; /* 240 8 */
unsigned char * tail; /* 248 8 */
/* --- cacheline 4 boundary (256 bytes) --- */
unsigned char * end; /* 256 8 */
}; /* size: 264, cachelines: 5 */
/* sum members: 260, holes: 1, sum holes: 4 */
/* bit holes: 1, sum bit holes: 2 bits */
/* last cacheline: 8 bytes */
On 32 bits nothing changes, and pointers continue to be used with the compiler
turning all this abstraction layer into dust. But there are some sk_buff
validation tricks that are now possible, humm... :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/skbuff.h | 104 |
1 files changed, 86 insertions, 18 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index c45ad1263271..2e7405500626 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -179,6 +179,16 @@ enum { SKB_GSO_TCPV6 = 1 << 4, }; +#if BITS_PER_LONG > 32 +#define NET_SKBUFF_DATA_USES_OFFSET 1 +#endif + +#ifdef NET_SKBUFF_DATA_USES_OFFSET +typedef unsigned int sk_buff_data_t; +#else +typedef unsigned char *sk_buff_data_t; +#endif + /** * struct sk_buff - socket buffer * @next: Next buffer in list @@ -236,9 +246,9 @@ struct sk_buff { int iif; /* 4 byte hole on 64 bit*/ - unsigned char *transport_header; - unsigned char *network_header; - unsigned char *mac_header; + sk_buff_data_t transport_header; + sk_buff_data_t network_header; + sk_buff_data_t mac_header; struct dst_entry *dst; struct sec_path *sp; @@ -942,50 +952,92 @@ static inline void skb_reserve(struct sk_buff *skb, int len) skb->tail += len; } +#ifdef NET_SKBUFF_DATA_USES_OFFSET static inline unsigned char *skb_transport_header(const struct sk_buff *skb) { - return skb->transport_header; + return skb->head + skb->transport_header; } static inline void skb_reset_transport_header(struct sk_buff *skb) { - skb->transport_header = skb->data; + skb->transport_header = skb->data - skb->head; } static inline void skb_set_transport_header(struct sk_buff *skb, const int offset) { - skb->transport_header = skb->data + offset; -} - -static inline int skb_transport_offset(const struct sk_buff *skb) -{ - return skb->transport_header - skb->data; + skb_reset_transport_header(skb); + skb->transport_header += offset; } static inline unsigned char *skb_network_header(const struct sk_buff *skb) { - return skb->network_header; + return skb->head + skb->network_header; } static inline void skb_reset_network_header(struct sk_buff *skb) { - skb->network_header = skb->data; + skb->network_header = skb->data - skb->head; } static inline void skb_set_network_header(struct sk_buff *skb, const int offset) { - skb->network_header = skb->data + offset; + skb_reset_network_header(skb); + skb->network_header += offset; } -static inline int skb_network_offset(const struct sk_buff *skb) +static inline unsigned char *skb_mac_header(const struct sk_buff *skb) { - return skb->network_header - skb->data; + return skb->head + skb->mac_header; } -static inline u32 skb_network_header_len(const struct sk_buff *skb) +static inline int skb_mac_header_was_set(const struct sk_buff *skb) { - return skb->transport_header - skb->network_header; + return skb->mac_header != ~0U; +} + +static inline void skb_reset_mac_header(struct sk_buff *skb) +{ + skb->mac_header = skb->data - skb->head; +} + +static inline void skb_set_mac_header(struct sk_buff *skb, const int offset) +{ + skb_reset_mac_header(skb); + skb->mac_header += offset; +} + +#else /* NET_SKBUFF_DATA_USES_OFFSET */ + +static inline unsigned char *skb_transport_header(const struct sk_buff *skb) +{ + return skb->transport_header; +} + +static inline void skb_reset_transport_header(struct sk_buff *skb) +{ + skb->transport_header = skb->data; +} + +static inline void skb_set_transport_header(struct sk_buff *skb, + const int offset) +{ + skb->transport_header = skb->data + offset; +} + +static inline unsigned char *skb_network_header(const struct sk_buff *skb) +{ + return skb->network_header; +} + +static inline void skb_reset_network_header(struct sk_buff *skb) +{ + skb->network_header = skb->data; +} + +static inline void skb_set_network_header(struct sk_buff *skb, const int offset) +{ + skb->network_header = skb->data + offset; } static inline unsigned char *skb_mac_header(const struct sk_buff *skb) @@ -1007,6 +1059,22 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset) { skb->mac_header = skb->data + offset; } +#endif /* NET_SKBUFF_DATA_USES_OFFSET */ + +static inline int skb_transport_offset(const struct sk_buff *skb) +{ + return skb_transport_header(skb) - skb->data; +} + +static inline u32 skb_network_header_len(const struct sk_buff *skb) +{ + return skb->transport_header - skb->network_header; +} + +static inline int skb_network_offset(const struct sk_buff *skb) +{ + return skb_network_header(skb) - skb->data; +} /* * CPUs often take a performance hit when accessing unaligned memory |