summaryrefslogtreecommitdiff
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 {
SKB_GSO_TCPV6 = 1 << 4,
};
+#if BITS_PER_LONG > 32
+#define NET_SKBUFF_DATA_USES_OFFSET 1
+#endif
+
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+typedef unsigned int sk_buff_data_t;
+#else
+typedef unsigned char *sk_buff_data_t;
+#endif
+
/**
* struct sk_buff - socket buffer
* @next: Next buffer in list
@@ -236,9 +246,9 @@ struct sk_buff {
int iif;
/* 4 byte hole on 64 bit*/
- unsigned char *transport_header;
- unsigned char *network_header;
- unsigned char *mac_header;
+ sk_buff_data_t transport_header;
+ sk_buff_data_t network_header;
+ sk_buff_data_t mac_header;
struct dst_entry *dst;
struct sec_path *sp;
@@ -942,50 +952,92 @@ static inline void skb_reserve(struct sk_buff *skb, int len)
skb->tail += len;
}
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
{
- return skb->transport_header;
+ return skb->head + skb->transport_header;
}
static inline void skb_reset_transport_header(struct sk_buff *skb)
{
- skb->transport_header = skb->data;
+ skb->transport_header = skb->data - skb->head;
}
static inline void skb_set_transport_header(struct sk_buff *skb,
const int offset)
{
- skb->transport_header = skb->data + offset;
-}
-
-static inline int skb_transport_offset(const struct sk_buff *skb)
-{
- return skb->transport_header - skb->data;
+ skb_reset_transport_header(skb);
+ skb->transport_header += offset;
}
static inline unsigned char *skb_network_header(const struct sk_buff *skb)
{
- return skb->network_header;
+ return skb->head + skb->network_header;
}
static inline void skb_reset_network_header(struct sk_buff *skb)
{
- skb->network_header = skb->data;
+ skb->network_header = skb->data - skb->head;
}
static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
{
- skb->network_header = skb->data + offset;
+ skb_reset_network_header(skb);
+ skb->network_header += offset;
}
-static inline int skb_network_offset(const struct sk_buff *skb)
+static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
{
- return skb->network_header - skb->data;
+ return skb->head + skb->mac_header;
}
-static inline u32 skb_network_header_len(const struct sk_buff *skb)
+static inline int skb_mac_header_was_set(const struct sk_buff *skb)
{
- return skb->transport_header - skb->network_header;
+ return skb->mac_header != ~0U;
+}
+
+static inline void skb_reset_mac_header(struct sk_buff *skb)
+{
+ skb->mac_header = skb->data - skb->head;
+}
+
+static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
+{
+ skb_reset_mac_header(skb);
+ skb->mac_header += offset;
+}
+
+#else /* NET_SKBUFF_DATA_USES_OFFSET */
+
+static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
+{
+ return skb->transport_header;
+}
+
+static inline void skb_reset_transport_header(struct sk_buff *skb)
+{
+ skb->transport_header = skb->data;
+}
+
+static inline void skb_set_transport_header(struct sk_buff *skb,
+ const int offset)
+{
+ skb->transport_header = skb->data + offset;
+}
+
+static inline unsigned char *skb_network_header(const struct sk_buff *skb)
+{
+ return skb->network_header;
+}
+
+static inline void skb_reset_network_header(struct sk_buff *skb)
+{
+ skb->network_header = skb->data;
+}
+
+static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
+{
+ skb->network_header = skb->data + offset;
}
static 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)
{
skb->mac_header = skb->data + offset;
}
+#endif /* NET_SKBUFF_DATA_USES_OFFSET */
+
+static inline int skb_transport_offset(const struct sk_buff *skb)
+{
+ return skb_transport_header(skb) - skb->data;
+}
+
+static inline u32 skb_network_header_len(const struct sk_buff *skb)
+{
+ return skb->transport_header - skb->network_header;
+}
+
+static inline int skb_network_offset(const struct sk_buff *skb)
+{
+ return skb_network_header(skb) - skb->data;
+}
/*
* 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)
static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
{
+#ifndef NET_SKBUFF_DATA_USES_OFFSET
/*
* Shift between the two data areas in bytes
*/
unsigned long offset = new->data - old->data;
-
+#endif
new->sk = NULL;
new->dev = old->dev;
new->priority = old->priority;
@@ -461,9 +462,15 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
#ifdef CONFIG_INET
new->sp = secpath_get(old->sp);
#endif
- new->transport_header = old->transport_header + offset;
- new->network_header = old->network_header + offset;
- new->mac_header = old->mac_header + offset;
+ new->transport_header = old->transport_header;
+ new->network_header = old->network_header;
+ new->mac_header = old->mac_header;
+#ifndef NET_SKBUFF_DATA_USES_OFFSET
+ /* {transport,network,mac}_header are relative to skb->head */
+ new->transport_header += offset;
+ new->network_header += offset;
+ new->mac_header += offset;
+#endif
memcpy(new->cb, old->cb, sizeof(old->cb));
new->local_df = old->local_df;
new->fclone = SKB_FCLONE_UNAVAILABLE;
@@ -639,9 +646,12 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
skb->end = data + size;
skb->data += off;
skb->tail += off;
+#ifndef NET_SKBUFF_DATA_USES_OFFSET
+ /* {transport,network,mac}_header are relative to skb->head */
skb->transport_header += off;
skb->network_header += off;
skb->mac_header += off;
+#endif
skb->cloned = 0;
skb->nohdr = 0;
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,
struct iphdr *old_iph = ip_hdr(skb);
u8 tos = old_iph->tos;
__be16 df = old_iph->frag_off;
- unsigned char *old_transport_header = skb->transport_header;
+ sk_buff_data_t old_transport_header = skb->transport_header;
struct iphdr *iph; /* Our new IP header */
int max_headroom; /* The extra header space needed */
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)
struct sctp_association *asoc = NULL;
struct sctp_transport *transport;
struct inet_sock *inet;
- char *saveip, *savesctp;
+ sk_buff_data_t saveip, savesctp;
int err;
if (skb->len < ihlen + 8) {
@@ -527,7 +527,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
skb_reset_network_header(skb);
skb_set_transport_header(skb, ihlen);
sk = sctp_err_lookup(AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
- /* Put back, the original pointers. */
+ /* Put back, the original values. */
skb->network_header = saveip;
skb->transport_header = savesctp;
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,
struct sctp_association *asoc;
struct sctp_transport *transport;
struct ipv6_pinfo *np;
- char *saveip, *savesctp;
+ sk_buff_data_t saveip, savesctp;
int err;
idev = in6_dev_get(skb->dev);