aboutsummaryrefslogtreecommitdiffstats
path: root/net
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
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')
-rw-r--r--net/core/skbuff.c18
-rw-r--r--net/ipv4/ipvs/ip_vs_xmit.c2
-rw-r--r--net/sctp/input.c4
-rw-r--r--net/sctp/ipv6.c2
4 files changed, 18 insertions, 8 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);
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
index fded9b2f227c..900ce29db382 100644
--- a/net/ipv4/ipvs/ip_vs_xmit.c
+++ b/net/ipv4/ipvs/ip_vs_xmit.c
@@ -323,7 +323,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
323 struct iphdr *old_iph = ip_hdr(skb); 323 struct iphdr *old_iph = ip_hdr(skb);
324 u8 tos = old_iph->tos; 324 u8 tos = old_iph->tos;
325 __be16 df = old_iph->frag_off; 325 __be16 df = old_iph->frag_off;
326 unsigned char *old_transport_header = skb->transport_header; 326 sk_buff_data_t old_transport_header = skb->transport_header;
327 struct iphdr *iph; /* Our new IP header */ 327 struct iphdr *iph; /* Our new IP header */
328 int max_headroom; /* The extra header space needed */ 328 int max_headroom; /* The extra header space needed */
329 int mtu; 329 int mtu;
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 87feee166da9..1ff47b18724a 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -513,7 +513,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
513 struct sctp_association *asoc = NULL; 513 struct sctp_association *asoc = NULL;
514 struct sctp_transport *transport; 514 struct sctp_transport *transport;
515 struct inet_sock *inet; 515 struct inet_sock *inet;
516 char *saveip, *savesctp; 516 sk_buff_data_t saveip, savesctp;
517 int err; 517 int err;
518 518
519 if (skb->len < ihlen + 8) { 519 if (skb->len < ihlen + 8) {
@@ -527,7 +527,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
527 skb_reset_network_header(skb); 527 skb_reset_network_header(skb);
528 skb_set_transport_header(skb, ihlen); 528 skb_set_transport_header(skb, ihlen);
529 sk = sctp_err_lookup(AF_INET, skb, sctp_hdr(skb), &asoc, &transport); 529 sk = sctp_err_lookup(AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
530 /* Put back, the original pointers. */ 530 /* Put back, the original values. */
531 skb->network_header = saveip; 531 skb->network_header = saveip;
532 skb->transport_header = savesctp; 532 skb->transport_header = savesctp;
533 if (!sk) { 533 if (!sk) {
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index afcb0093c290..5b0cdda4b449 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -126,7 +126,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
126 struct sctp_association *asoc; 126 struct sctp_association *asoc;
127 struct sctp_transport *transport; 127 struct sctp_transport *transport;
128 struct ipv6_pinfo *np; 128 struct ipv6_pinfo *np;
129 char *saveip, *savesctp; 129 sk_buff_data_t saveip, savesctp;
130 int err; 130 int err;
131 131
132 idev = in6_dev_get(skb->dev); 132 idev = in6_dev_get(skb->dev);