aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/skbuff.h104
-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
5 files changed, 104 insertions, 26 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 {
179 SKB_GSO_TCPV6 = 1 << 4, 179 SKB_GSO_TCPV6 = 1 << 4,
180}; 180};
181 181
182#if BITS_PER_LONG > 32
183#define NET_SKBUFF_DATA_USES_OFFSET 1
184#endif
185
186#ifdef NET_SKBUFF_DATA_USES_OFFSET
187typedef unsigned int sk_buff_data_t;
188#else
189typedef unsigned char *sk_buff_data_t;
190#endif
191
182/** 192/**
183 * struct sk_buff - socket buffer 193 * struct sk_buff - socket buffer
184 * @next: Next buffer in list 194 * @next: Next buffer in list
@@ -236,9 +246,9 @@ struct sk_buff {
236 int iif; 246 int iif;
237 /* 4 byte hole on 64 bit*/ 247 /* 4 byte hole on 64 bit*/
238 248
239 unsigned char *transport_header; 249 sk_buff_data_t transport_header;
240 unsigned char *network_header; 250 sk_buff_data_t network_header;
241 unsigned char *mac_header; 251 sk_buff_data_t mac_header;
242 struct dst_entry *dst; 252 struct dst_entry *dst;
243 struct sec_path *sp; 253 struct sec_path *sp;
244 254
@@ -942,50 +952,92 @@ static inline void skb_reserve(struct sk_buff *skb, int len)
942 skb->tail += len; 952 skb->tail += len;
943} 953}
944 954
955#ifdef NET_SKBUFF_DATA_USES_OFFSET
945static inline unsigned char *skb_transport_header(const struct sk_buff *skb) 956static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
946{ 957{
947 return skb->transport_header; 958 return skb->head + skb->transport_header;
948} 959}
949 960
950static inline void skb_reset_transport_header(struct sk_buff *skb) 961static inline void skb_reset_transport_header(struct sk_buff *skb)
951{ 962{
952 skb->transport_header = skb->data; 963 skb->transport_header = skb->data - skb->head;
953} 964}
954 965
955static inline void skb_set_transport_header(struct sk_buff *skb, 966static inline void skb_set_transport_header(struct sk_buff *skb,
956 const int offset) 967 const int offset)
957{ 968{
958 skb->transport_header = skb->data + offset; 969 skb_reset_transport_header(skb);
959} 970 skb->transport_header += offset;
960
961static inline int skb_transport_offset(const struct sk_buff *skb)
962{
963 return skb->transport_header - skb->data;
964} 971}
965 972
966static inline unsigned char *skb_network_header(const struct sk_buff *skb) 973static inline unsigned char *skb_network_header(const struct sk_buff *skb)
967{ 974{
968 return skb->network_header; 975 return skb->head + skb->network_header;
969} 976}
970 977
971static inline void skb_reset_network_header(struct sk_buff *skb) 978static inline void skb_reset_network_header(struct sk_buff *skb)
972{ 979{
973 skb->network_header = skb->data; 980 skb->network_header = skb->data - skb->head;
974} 981}
975 982
976static inline void skb_set_network_header(struct sk_buff *skb, const int offset) 983static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
977{ 984{
978 skb->network_header = skb->data + offset; 985 skb_reset_network_header(skb);
986 skb->network_header += offset;
979} 987}
980 988
981static inline int skb_network_offset(const struct sk_buff *skb) 989static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
982{ 990{
983 return skb->network_header - skb->data; 991 return skb->head + skb->mac_header;
984} 992}
985 993
986static inline u32 skb_network_header_len(const struct sk_buff *skb) 994static inline int skb_mac_header_was_set(const struct sk_buff *skb)
987{ 995{
988 return skb->transport_header - skb->network_header; 996 return skb->mac_header != ~0U;
997}
998
999static inline void skb_reset_mac_header(struct sk_buff *skb)
1000{
1001 skb->mac_header = skb->data - skb->head;
1002}
1003
1004static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
1005{
1006 skb_reset_mac_header(skb);
1007 skb->mac_header += offset;
1008}
1009
1010#else /* NET_SKBUFF_DATA_USES_OFFSET */
1011
1012static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
1013{
1014 return skb->transport_header;
1015}
1016
1017static inline void skb_reset_transport_header(struct sk_buff *skb)
1018{
1019 skb->transport_header = skb->data;
1020}
1021
1022static inline void skb_set_transport_header(struct sk_buff *skb,
1023 const int offset)
1024{
1025 skb->transport_header = skb->data + offset;
1026}
1027
1028static inline unsigned char *skb_network_header(const struct sk_buff *skb)
1029{
1030 return skb->network_header;
1031}
1032
1033static inline void skb_reset_network_header(struct sk_buff *skb)
1034{
1035 skb->network_header = skb->data;
1036}
1037
1038static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
1039{
1040 skb->network_header = skb->data + offset;
989} 1041}
990 1042
991static inline unsigned char *skb_mac_header(const struct sk_buff *skb) 1043static 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)
1007{ 1059{
1008 skb->mac_header = skb->data + offset; 1060 skb->mac_header = skb->data + offset;
1009} 1061}
1062#endif /* NET_SKBUFF_DATA_USES_OFFSET */
1063
1064static inline int skb_transport_offset(const struct sk_buff *skb)
1065{
1066 return skb_transport_header(skb) - skb->data;
1067}
1068
1069static inline u32 skb_network_header_len(const struct sk_buff *skb)
1070{
1071 return skb->transport_header - skb->network_header;
1072}
1073
1074static inline int skb_network_offset(const struct sk_buff *skb)
1075{
1076 return skb_network_header(skb) - skb->data;
1077}
1010 1078
1011/* 1079/*
1012 * CPUs often take a performance hit when accessing unaligned memory 1080 * CPUs often take a performance hit when accessing unaligned memory
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);