Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[IPSEC]: Set skb->data to payload in x->mode->output

This patch changes the calling convention so that on entry from
x->mode->output and before entry into x->type->output skb->data
will point to the payload instead of the IP header.

This is essentially a redistribution of skb_push/skb_pull calls
with the aim of minimising them on the common path of tunnel +
ESP.

It'll also let us use the same calling convention between IPv4
and IPv6 with the next patch.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Herbert Xu and committed by
David S. Miller
7b277b1a bee0b40c

+47 -42
+1
net/ipv4/ah4.c
··· 66 66 char buf[60]; 67 67 } tmp_iph; 68 68 69 + skb_push(skb, -skb_network_offset(skb)); 69 70 top_iph = ip_hdr(skb); 70 71 iph = &tmp_iph.iph; 71 72
+2 -4
net/ipv4/esp4.c
··· 28 28 int alen; 29 29 int nfrags; 30 30 31 - /* Strip IP+ESP header. */ 32 - __skb_pull(skb, skb_transport_offset(skb)); 33 - /* Now skb is pure payload to encrypt */ 31 + /* skb is pure payload to encrypt */ 34 32 35 33 err = -ENOMEM; 36 34 ··· 58 60 tail[clen - skb->len - 2] = (clen - skb->len) - 2; 59 61 pskb_put(skb, trailer, clen - skb->len); 60 62 61 - __skb_push(skb, -skb_network_offset(skb)); 63 + skb_push(skb, -skb_network_offset(skb)); 62 64 top_iph = ip_hdr(skb); 63 65 esph = (struct ip_esp_hdr *)(skb_network_header(skb) + 64 66 top_iph->ihl * 4);
+1
net/ipv4/ipcomp.c
··· 134 134 int hdr_len = 0; 135 135 struct iphdr *iph = ip_hdr(skb); 136 136 137 + skb_push(skb, -skb_network_offset(skb)); 137 138 iph->tot_len = htons(skb->len); 138 139 hdr_len = iph->ihl * 4; 139 140 if ((skb->len - hdr_len) < ipcd->threshold) {
+3 -2
net/ipv4/xfrm4_mode_beet.c
··· 40 40 if (unlikely(optlen)) 41 41 hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4); 42 42 43 - skb_push(skb, x->props.header_len - IPV4_BEET_PHMAXLEN + hdrlen); 44 - skb_reset_network_header(skb); 43 + skb_set_network_header(skb, IPV4_BEET_PHMAXLEN - x->props.header_len - 44 + hdrlen); 45 45 top_iph = ip_hdr(skb); 46 46 skb->transport_header += sizeof(*iph) - hdrlen; 47 + __skb_pull(skb, sizeof(*iph) - hdrlen); 47 48 48 49 memmove(top_iph, iph, sizeof(*iph)); 49 50 if (unlikely(optlen)) {
+2 -2
net/ipv4/xfrm4_mode_transport.c
··· 27 27 int ihl = iph->ihl * 4; 28 28 29 29 skb->transport_header = skb->network_header + ihl; 30 - skb_push(skb, x->props.header_len); 31 - skb_reset_network_header(skb); 30 + skb_set_network_header(skb, -x->props.header_len); 31 + __skb_pull(skb, ihl); 32 32 memmove(skb_network_header(skb), iph, ihl); 33 33 return 0; 34 34 }
+1 -2
net/ipv4/xfrm4_mode_tunnel.c
··· 49 49 iph = ip_hdr(skb); 50 50 skb->transport_header = skb->network_header; 51 51 52 - skb_push(skb, x->props.header_len); 53 - skb_reset_network_header(skb); 52 + skb_set_network_header(skb, -x->props.header_len); 54 53 top_iph = ip_hdr(skb); 55 54 56 55 top_iph->ihl = 5;
+1
net/ipv4/xfrm4_tunnel.c
··· 14 14 { 15 15 struct iphdr *iph = ip_hdr(skb); 16 16 17 + skb_push(skb, -skb_network_offset(skb)); 17 18 iph->tot_len = htons(skb->len); 18 19 ip_send_check(iph); 19 20
+1
net/ipv6/ah6.c
··· 236 236 char hdrs[0]; 237 237 } *tmp_ext; 238 238 239 + skb_push(skb, -skb_network_offset(skb)); 239 240 top_iph = ipv6_hdr(skb); 240 241 top_iph->payload_len = htons(skb->len - sizeof(*top_iph)); 241 242
+2 -7
net/ipv6/esp6.c
··· 54 54 int nfrags; 55 55 u8 *tail; 56 56 struct esp_data *esp = x->data; 57 - int hdr_len = (skb_transport_offset(skb) + 58 - sizeof(*esph) + esp->conf.ivlen); 59 57 60 - /* Strip IP+ESP header. */ 61 - __skb_pull(skb, hdr_len); 62 - 63 - /* Now skb is pure payload to encrypt */ 58 + /* skb is pure payload to encrypt */ 64 59 err = -ENOMEM; 65 60 66 61 /* Round to block size */ ··· 84 89 tail[clen-skb->len - 2] = (clen - skb->len) - 2; 85 90 pskb_put(skb, trailer, clen - skb->len); 86 91 87 - __skb_push(skb, -skb_network_offset(skb)); 92 + skb_push(skb, -skb_network_offset(skb)); 88 93 top_iph = ipv6_hdr(skb); 89 94 esph = (struct ipv6_esp_hdr *)skb_transport_header(skb); 90 95 top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph));
+4 -1
net/ipv6/ipcomp6.c
··· 128 128 u8 *start, *scratch; 129 129 struct crypto_comp *tfm; 130 130 int cpu; 131 - int hdr_len = skb_transport_offset(skb); 131 + int hdr_len; 132 + 133 + skb_push(skb, -skb_network_offset(skb)); 134 + hdr_len = skb_transport_offset(skb); 132 135 133 136 /* check whether datagram len is larger than threshold */ 134 137 if ((skb->len - hdr_len) < ipcd->threshold) {
+2
net/ipv6/mip6.c
··· 153 153 u8 nexthdr; 154 154 int len; 155 155 156 + skb_push(skb, -skb_network_offset(skb)); 156 157 iph = ipv6_hdr(skb); 157 158 iph->payload_len = htons(skb->len - sizeof(*iph)); 158 159 ··· 368 367 struct rt2_hdr *rt2; 369 368 u8 nexthdr; 370 369 370 + skb_push(skb, -skb_network_offset(skb)); 371 371 iph = ipv6_hdr(skb); 372 372 iph->payload_len = htons(skb->len - sizeof(*iph)); 373 373
+7 -6
net/ipv6/xfrm6_mode_beet.c
··· 29 29 * filled in by x->type->output and the mac header will be set to the 30 30 * nextheader field of the extension header directly preceding the 31 31 * encapsulation header, or in its absence, that of the top IP header. 32 - * The value of skb->data and the network header will always point to the 33 - * top IP header. 32 + * The value of the network header will always point to the top IP header 33 + * while skb->data will point to the payload. 34 34 */ 35 35 static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) 36 36 { ··· 38 38 u8 *prevhdr; 39 39 int hdr_len; 40 40 41 - skb_push(skb, x->props.header_len); 42 41 iph = ipv6_hdr(skb); 43 42 44 43 hdr_len = ip6_find_1stfragopt(skb, &prevhdr); 45 - memmove(skb->data, iph, hdr_len); 46 44 47 45 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); 48 - skb_reset_network_header(skb); 49 - skb_set_transport_header(skb, hdr_len); 46 + skb_set_network_header(skb, -x->props.header_len); 47 + skb_set_transport_header(skb, hdr_len - x->props.header_len); 48 + __skb_pull(skb, hdr_len); 49 + 50 50 top_iph = ipv6_hdr(skb); 51 + memmove(top_iph, iph, hdr_len); 51 52 52 53 ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); 53 54 ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
+6 -6
net/ipv6/xfrm6_mode_ro.c
··· 42 42 * filled in by x->type->output and the mac header will be set to the 43 43 * nextheader field of the extension header directly preceding the 44 44 * encapsulation header, or in its absence, that of the top IP header. 45 - * The value of skb->data and the network header will always point to the 46 - * top IP header. 45 + * The value of the network header will always point to the top IP header 46 + * while skb->data will point to the payload. 47 47 */ 48 48 static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb) 49 49 { ··· 51 51 u8 *prevhdr; 52 52 int hdr_len; 53 53 54 - skb_push(skb, x->props.header_len); 55 54 iph = ipv6_hdr(skb); 56 55 57 56 hdr_len = x->type->hdr_offset(x, skb, &prevhdr); 58 57 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); 59 - skb_reset_network_header(skb); 60 - skb_set_transport_header(skb, hdr_len); 61 - memmove(skb->data, iph, hdr_len); 58 + skb_set_network_header(skb, -x->props.header_len); 59 + skb_set_transport_header(skb, hdr_len - x->props.header_len); 60 + __skb_pull(skb, hdr_len); 61 + memmove(ipv6_hdr(skb), iph, hdr_len); 62 62 63 63 x->lastused = get_seconds(); 64 64
+6 -6
net/ipv6/xfrm6_mode_transport.c
··· 23 23 * filled in by x->type->output and the mac header will be set to the 24 24 * nextheader field of the extension header directly preceding the 25 25 * encapsulation header, or in its absence, that of the top IP header. 26 - * The value of skb->data and the network header will always point to the 27 - * top IP header. 26 + * The value of the network header will always point to the top IP header 27 + * while skb->data will point to the payload. 28 28 */ 29 29 static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb) 30 30 { ··· 32 32 u8 *prevhdr; 33 33 int hdr_len; 34 34 35 - skb_push(skb, x->props.header_len); 36 35 iph = ipv6_hdr(skb); 37 36 38 37 hdr_len = x->type->hdr_offset(x, skb, &prevhdr); 39 38 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); 40 - skb_reset_network_header(skb); 41 - skb_set_transport_header(skb, hdr_len); 42 - memmove(skb->data, iph, hdr_len); 39 + skb_set_network_header(skb, -x->props.header_len); 40 + skb_set_transport_header(skb, hdr_len - x->props.header_len); 41 + __skb_pull(skb, hdr_len); 42 + memmove(ipv6_hdr(skb), iph, hdr_len); 43 43 return 0; 44 44 } 45 45
+7 -6
net/ipv6/xfrm6_mode_tunnel.c
··· 41 41 * filled in by x->type->output and the mac header will be set to the 42 42 * nextheader field of the extension header directly preceding the 43 43 * encapsulation header, or in its absence, that of the top IP header. 44 - * The value of skb->data and the network header will always point to the 45 - * top IP header. 44 + * The value of the network header will always point to the top IP header 45 + * while skb->data will point to the payload. 46 46 */ 47 47 static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) 48 48 { ··· 51 51 struct ipv6hdr *iph, *top_iph; 52 52 int dsfield; 53 53 54 - skb_push(skb, x->props.header_len); 55 54 iph = ipv6_hdr(skb); 56 55 57 - skb_set_mac_header(skb, offsetof(struct ipv6hdr, nexthdr)); 58 - skb_reset_network_header(skb); 59 - skb_set_transport_header(skb, sizeof(struct ipv6hdr)); 56 + skb_set_mac_header(skb, offsetof(struct ipv6hdr, nexthdr) - 57 + x->props.header_len); 58 + skb_set_network_header(skb, -x->props.header_len); 59 + skb_set_transport_header(skb, sizeof(struct ipv6hdr) - 60 + x->props.header_len); 60 61 top_iph = ipv6_hdr(skb); 61 62 62 63 top_iph->version = 6;
+1
net/ipv6/xfrm6_tunnel.c
··· 244 244 { 245 245 struct ipv6hdr *top_iph; 246 246 247 + skb_push(skb, -skb_network_offset(skb)); 247 248 top_iph = ipv6_hdr(skb); 248 249 top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); 249 250