aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/skbuff.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2007-04-11 00:22:35 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:26:21 -0400
commit2e07fa9cd3bac1e28cfe3131ed86b053afb02fc9 (patch)
tree177ad0c2cbbd60c25e54b35802219634c047aa08 /net/core/skbuff.c
parentb0e380b1d8a8e0aca215df97702f99815f05c094 (diff)
[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 'net/core/skbuff.c')
-rw-r--r--net/core/skbuff.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 1e71764be4a4..a48b08681261 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -448,11 +448,12 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
448 448
449static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) 449static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
450{ 450{
451#ifndef NET_SKBUFF_DATA_USES_OFFSET
451 /* 452 /*
452 * Shift between the two data areas in bytes 453 * Shift between the two data areas in bytes
453 */ 454 */
454 unsigned long offset = new->data - old->data; 455 unsigned long offset = new->data - old->data;
455 456#endif
456 new->sk = NULL; 457 new->sk = NULL;
457 new->dev = old->dev; 458 new->dev = old->dev;
458 new->priority = old->priority; 459 new->priority = old->priority;
@@ -461,9 +462,15 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
461#ifdef CONFIG_INET 462#ifdef CONFIG_INET
462 new->sp = secpath_get(old->sp); 463 new->sp = secpath_get(old->sp);
463#endif 464#endif
464 new->transport_header = old->transport_header + offset; 465 new->transport_header = old->transport_header;
465 new->network_header = old->network_header + offset; 466 new->network_header = old->network_header;
466 new->mac_header = old->mac_header + offset; 467 new->mac_header = old->mac_header;
468#ifndef NET_SKBUFF_DATA_USES_OFFSET
469 /* {transport,network,mac}_header are relative to skb->head */
470 new->transport_header += offset;
471 new->network_header += offset;
472 new->mac_header += offset;
473#endif
467 memcpy(new->cb, old->cb, sizeof(old->cb)); 474 memcpy(new->cb, old->cb, sizeof(old->cb));
468 new->local_df = old->local_df; 475 new->local_df = old->local_df;
469 new->fclone = SKB_FCLONE_UNAVAILABLE; 476 new->fclone = SKB_FCLONE_UNAVAILABLE;
@@ -639,9 +646,12 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
639 skb->end = data + size; 646 skb->end = data + size;
640 skb->data += off; 647 skb->data += off;
641 skb->tail += off; 648 skb->tail += off;
649#ifndef NET_SKBUFF_DATA_USES_OFFSET
650 /* {transport,network,mac}_header are relative to skb->head */
642 skb->transport_header += off; 651 skb->transport_header += off;
643 skb->network_header += off; 652 skb->network_header += off;
644 skb->mac_header += off; 653 skb->mac_header += off;
654#endif
645 skb->cloned = 0; 655 skb->cloned = 0;
646 skb->nohdr = 0; 656 skb->nohdr = 0;
647 atomic_set(&skb_shinfo(skb)->dataref, 1); 657 atomic_set(&skb_shinfo(skb)->dataref, 1);