__wsum skb_checksum(const struct sk_buff *skb, int offset, int len,
                    __wsum csum);
 
-static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
-                                      int len, void *buffer)
+static inline void *__skb_header_pointer(const struct sk_buff *skb, int offset,
+                                        int len, void *data, int hlen, void *buffer)
 {
-       int hlen = skb_headlen(skb);
-
        if (hlen - offset >= len)
-               return skb->data + offset;
+               return data + offset;
 
-       if (skb_copy_bits(skb, offset, buffer, len) < 0)
+       if (!skb ||
+           skb_copy_bits(skb, offset, buffer, len) < 0)
                return NULL;
 
        return buffer;
 }
 
+static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
+                                      int len, void *buffer)
+{
+       return __skb_header_pointer(skb, offset, len, skb->data,
+                                   skb_headlen(skb), buffer);
+}
+
 /**
  *     skb_needs_linearize - check if we need to linearize a given skb
  *                           depending on the given device features.
 
        u8 ip_proto;
 };
 
-bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow);
-__be32 skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto);
+bool __skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow,
+                       void *data, int hlen);
+static inline bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow)
+{
+       return __skb_flow_dissect(skb, flow, NULL, 0);
+}
+__be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,
+                           void *data, int hlen_proto);
+static inline __be32 skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto)
+{
+       return __skb_flow_get_ports(skb, thoff, ip_proto, NULL, 0);
+}
 u32 flow_hash_from_keys(struct flow_keys *keys);
 #endif
 
  * The function will try to retrieve the ports at offset thoff + poff where poff
  * is the protocol port offset returned from proto_ports_offset
  */
-__be32 skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto)
+__be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,
+                           void *data, int hlen)
 {
        int poff = proto_ports_offset(ip_proto);
 
+       if (!data) {
+               data = skb->data;
+               hlen = skb_headlen(skb);
+       }
+
        if (poff >= 0) {
                __be32 *ports, _ports;
 
-               ports = skb_header_pointer(skb, thoff + poff,
-                                          sizeof(_ports), &_ports);
+               ports = __skb_header_pointer(skb, thoff + poff,
+                                            sizeof(_ports), data, hlen, &_ports);
                if (ports)
                        return *ports;
        }
 
        return 0;
 }
-EXPORT_SYMBOL(skb_flow_get_ports);
+EXPORT_SYMBOL(__skb_flow_get_ports);
 
-bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow)
+bool __skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow, void *data, int hlen)
 {
        int nhoff = skb_network_offset(skb);
        u8 ip_proto;
        __be16 proto = skb->protocol;
 
+       if (!data) {
+               data = skb->data;
+               hlen = skb_headlen(skb);
+       }
+
        memset(flow, 0, sizeof(*flow));
 
 again:
                const struct iphdr *iph;
                struct iphdr _iph;
 ip:
-               iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
+               iph = __skb_header_pointer(skb, nhoff, sizeof(_iph), data, hlen, &_iph);
                if (!iph || iph->ihl < 5)
                        return false;
                nhoff += iph->ihl * 4;
                __be32 flow_label;
 
 ipv6:
-               iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
+               iph = __skb_header_pointer(skb, nhoff, sizeof(_iph), data, hlen, &_iph);
                if (!iph)
                        return false;
 
                const struct vlan_hdr *vlan;
                struct vlan_hdr _vlan;
 
-               vlan = skb_header_pointer(skb, nhoff, sizeof(_vlan), &_vlan);
+               vlan = __skb_header_pointer(skb, nhoff, sizeof(_vlan), data, hlen, &_vlan);
                if (!vlan)
                        return false;
 
                        struct pppoe_hdr hdr;
                        __be16 proto;
                } *hdr, _hdr;
-               hdr = skb_header_pointer(skb, nhoff, sizeof(_hdr), &_hdr);
+               hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, &_hdr);
                if (!hdr)
                        return false;
                proto = hdr->proto;
                        __be16 proto;
                } *hdr, _hdr;
 
-               hdr = skb_header_pointer(skb, nhoff, sizeof(_hdr), &_hdr);
+               hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, &_hdr);
                if (!hdr)
                        return false;
                /*
                                const struct ethhdr *eth;
                                struct ethhdr _eth;
 
-                               eth = skb_header_pointer(skb, nhoff,
-                                                        sizeof(_eth), &_eth);
+                               eth = __skb_header_pointer(skb, nhoff,
+                                                          sizeof(_eth),
+                                                          data, hlen, &_eth);
                                if (!eth)
                                        return false;
                                proto = eth->h_proto;
 
        flow->n_proto = proto;
        flow->ip_proto = ip_proto;
-       flow->ports = skb_flow_get_ports(skb, nhoff, ip_proto);
+       flow->ports = __skb_flow_get_ports(skb, nhoff, ip_proto, data, hlen);
        flow->thoff = (u16) nhoff;
 
        return true;
 }
-EXPORT_SYMBOL(skb_flow_dissect);
+EXPORT_SYMBOL(__skb_flow_dissect);
 
 static u32 hashrnd __read_mostly;
 static __always_inline void __flow_hash_secret_init(void)