[SK_BUFF]: Convert skb->tail to sk_buff_data_t

So that it is also an offset from skb->head, reduces its size from 8 to 4 bytes
on 64bit architectures, allowing us to combine the 4 bytes hole left by the
layer headers conversion, reducing struct sk_buff size to 256 bytes, i.e. 4
64byte cachelines, and since the sk_buff slab cache is SLAB_HWCACHE_ALIGN...
:-)

Many calculations that previously required that skb->{transport,network,
mac}_header be first converted to a pointer now can be done directly, being
meaningful as offsets or pointers.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index f16f4f0..4a355fe 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -268,7 +268,7 @@
 	serr->addr_offset = (u8 *)&iph->daddr - skb_network_header(skb);
 	serr->port = fl->fl_ip_dport;
 
-	__skb_pull(skb, skb->tail - skb->data);
+	__skb_pull(skb, skb_tail_pointer(skb) - skb->data);
 	skb_reset_transport_header(skb);
 
 	if (sock_queue_err_skb(sk, skb))
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 7fdf84d..b8e8914 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -51,6 +51,7 @@
 	int clen;
 	int alen;
 	int nfrags;
+	u8 *tail;
 	struct esp_data *esp = x->data;
 	int hdr_len = (skb_transport_offset(skb) +
 		       sizeof(*esph) + esp->conf.ivlen);
@@ -78,18 +79,19 @@
 	}
 
 	/* Fill padding... */
+	tail = skb_tail_pointer(trailer);
 	do {
 		int i;
 		for (i=0; i<clen-skb->len - 2; i++)
-			*(u8*)(trailer->tail + i) = i+1;
+			tail[i] = i + 1;
 	} while (0);
-	*(u8*)(trailer->tail + clen-skb->len - 2) = (clen - skb->len)-2;
+	tail[clen-skb->len - 2] = (clen - skb->len) - 2;
 	pskb_put(skb, trailer, clen - skb->len);
 
 	top_iph = (struct ipv6hdr *)__skb_push(skb, hdr_len);
 	esph = (struct ipv6_esp_hdr *)skb_transport_header(skb);
 	top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph));
-	*(u8 *)(trailer->tail - 1) = *skb_network_header(skb);
+	*(skb_tail_pointer(skb) - 1) = *skb_network_header(skb);
 	*skb_network_header(skb) = IPPROTO_ESP;
 
 	esph->spi = x->id.spi;
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index a6a275d..275d2e8 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -51,7 +51,7 @@
 int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
 {
 	const unsigned char *nh = skb_network_header(skb);
-	int packet_len = skb->tail - nh;
+	int packet_len = skb->tail - skb->network_header;
 	struct ipv6_opt_hdr *hdr;
 	int len;
 
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index d3edc3c..e94992a 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -317,7 +317,8 @@
 	int hlimit, tclass;
 	int err = 0;
 
-	if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail)
+	if ((u8 *)hdr < skb->head ||
+	    (skb->network_header + sizeof(*hdr)) > skb->tail)
 		return;
 
 	/*
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index b2c092c..e2b8db6 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -514,7 +514,7 @@
 	u16 offset = sizeof(struct ipv6hdr);
 	struct ipv6_opt_hdr *exthdr =
 				(struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
-	unsigned int packet_len = skb->tail - skb_network_header(skb);
+	unsigned int packet_len = skb->tail - skb->network_header;
 	int found_rhdr = 0;
 	*nexthdr = &ipv6_hdr(skb)->nexthdr;
 
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 4c45bcc..6c27589 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1423,7 +1423,7 @@
 
 	memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
 
-	skb_set_transport_header(skb, skb->tail - skb->data);
+	skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data);
 	skb_put(skb, sizeof(*pmr));
 	pmr = (struct mld2_report *)skb_transport_header(skb);
 	pmr->type = ICMPV6_MLD2_REPORT;
@@ -1468,8 +1468,8 @@
 	int err;
 
 	IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
-	payload_len = skb->tail - skb_network_header(skb) - sizeof(*pip6);
-	mldlen = skb->tail - skb_transport_header(skb);
+	payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
+	mldlen = skb->tail - skb->transport_header;
 	pip6->payload_len = htons(payload_len);
 
 	pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index f0288e9..6ed763e 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -260,7 +260,7 @@
 	struct ipv6_opt_hdr *exthdr =
 				   (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
 	const unsigned char *nh = skb_network_header(skb);
-	unsigned int packet_len = skb->tail - nh;
+	unsigned int packet_len = skb->tail - skb->network_header;
 	int found_rhdr = 0;
 
 	*nexthdr = &ipv6_hdr(skb)->nexthdr;
@@ -392,7 +392,7 @@
 	struct ipv6_opt_hdr *exthdr =
 				   (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
 	const unsigned char *nh = skb_network_header(skb);
-	unsigned int packet_len = skb->tail - nh;
+	unsigned int packet_len = skb->tail - skb->network_header;
 	int found_rhdr = 0;
 
 	*nexthdr = &ipv6_hdr(skb)->nexthdr;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index f8e6197..b1cf708 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -492,7 +492,7 @@
 	skb_reserve(skb, LL_RESERVED_SPACE(dev));
 	ip6_nd_hdr(sk, skb, dev, src_addr, daddr, IPPROTO_ICMPV6, len);
 
-	skb_set_transport_header(skb, skb->tail - skb->data);
+	skb->transport_header = skb->tail;
 	skb_put(skb, len);
 	msg = (struct nd_msg *)skb_transport_header(skb);
 
@@ -584,7 +584,7 @@
 	skb_reserve(skb, LL_RESERVED_SPACE(dev));
 	ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
 
-	skb_set_transport_header(skb, skb->tail - skb->data);
+	skb->transport_header = skb->tail;
 	skb_put(skb, len);
 	msg = (struct nd_msg *)skb_transport_header(skb);
 	msg->icmph.icmp6_type = NDISC_NEIGHBOUR_SOLICITATION;
@@ -685,7 +685,7 @@
 	skb_reserve(skb, LL_RESERVED_SPACE(dev));
 	ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
 
-	skb_set_transport_header(skb, skb->tail - skb->data);
+	skb->transport_header = skb->tail;
 	skb_put(skb, len);
 	hdr = icmp6_hdr(skb);
 	hdr->icmp6_type = NDISC_ROUTER_SOLICITATION;
@@ -767,7 +767,8 @@
 	struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
 	struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
 	u8 *lladdr = NULL;
-	u32 ndoptlen = skb->tail - msg->opt;
+	u32 ndoptlen = skb->tail - (skb->transport_header +
+				    offsetof(struct nd_msg, opt));
 	struct ndisc_options ndopts;
 	struct net_device *dev = skb->dev;
 	struct inet6_ifaddr *ifp;
@@ -945,7 +946,8 @@
 	struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
 	struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
 	u8 *lladdr = NULL;
-	u32 ndoptlen = skb->tail - msg->opt;
+	u32 ndoptlen = skb->tail - (skb->transport_header +
+				    offsetof(struct nd_msg, opt));
 	struct ndisc_options ndopts;
 	struct net_device *dev = skb->dev;
 	struct inet6_ifaddr *ifp;
@@ -1111,8 +1113,7 @@
 
 	__u8 * opt = (__u8 *)(ra_msg + 1);
 
-	optlen = (skb->tail - skb_transport_header(skb)) -
-		  sizeof(struct ra_msg);
+	optlen = (skb->tail - skb->transport_header) - sizeof(struct ra_msg);
 
 	if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
 		ND_PRINTK2(KERN_WARNING
@@ -1361,7 +1362,7 @@
 		return;
 	}
 
-	optlen = skb->tail - skb_transport_header(skb);
+	optlen = skb->tail - skb->transport_header;
 	optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
 
 	if (optlen < 0) {
@@ -1522,7 +1523,7 @@
 	ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr,
 		   IPPROTO_ICMPV6, len);
 
-	skb_set_transport_header(buff, buff->tail - buff->data);
+	skb_set_transport_header(buff, skb_tail_pointer(buff) - buff->data);
 	skb_put(buff, len);
 	icmph = icmp6_hdr(buff);
 
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 66a2c41..5cfce21 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -189,7 +189,7 @@
 static struct sk_buff *
 ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
 {
-	unsigned char *old_tail;
+	sk_buff_data_t old_tail;
 	size_t size = 0;
 	size_t data_len = 0;
 	struct sk_buff *skb;
@@ -233,7 +233,7 @@
 	if (!skb)
 		goto nlmsg_failure;
 
-	old_tail= skb->tail;
+	old_tail = skb->tail;
 	nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh));
 	pmsg = NLMSG_DATA(nlh);
 	memset(pmsg, 0, sizeof(*pmsg));
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 8705f6a..2b3be68 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -1077,7 +1077,7 @@
 			spin_lock_bh(&sk->sk_receive_queue.lock);
 			skb = skb_peek(&sk->sk_receive_queue);
 			if (skb != NULL)
-				amount = skb->tail - skb_transport_header(skb);
+				amount = skb->tail - skb->transport_header;
 			spin_unlock_bh(&sk->sk_receive_queue.lock);
 			return put_user(amount, (int __user *)arg);
 		}