unsigned int size;
        const __be32 *ap;
        __be32 _addrs[8];
+       struct {
+               __be16 sport;
+               __be16 dport;
+       } _inet_hdr, *inet_hdr;
 
        memset(tuple, 0, sizeof(*tuple));
 
        tuple->dst.protonum = protonum;
        tuple->dst.dir = IP_CT_DIR_ORIGINAL;
 
-       return l4proto->pkt_to_tuple(skb, dataoff, net, tuple);
+       if (unlikely(l4proto->pkt_to_tuple))
+               return l4proto->pkt_to_tuple(skb, dataoff, net, tuple);
+
+       /* Actually only need first 4 bytes to get ports. */
+       inet_hdr = skb_header_pointer(skb, dataoff, sizeof(_inet_hdr), &_inet_hdr);
+       if (!inet_hdr)
+               return false;
+
+       tuple->src.u.udp.port = inet_hdr->sport;
+       tuple->dst.u.udp.port = inet_hdr->dport;
+       return true;
 }
 
 static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
 
        return &net->ct.nf_ct_proto.dccp;
 }
 
-static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
-                             struct net *net, struct nf_conntrack_tuple *tuple)
-{
-       struct dccp_hdr _hdr, *dh;
-
-       /* Actually only need first 4 bytes to get ports. */
-       dh = skb_header_pointer(skb, dataoff, 4, &_hdr);
-       if (dh == NULL)
-               return false;
-
-       tuple->src.u.dccp.port = dh->dccph_sport;
-       tuple->dst.u.dccp.port = dh->dccph_dport;
-       return true;
-}
-
 static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
                     unsigned int dataoff, unsigned int *timeouts)
 {
 const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 = {
        .l3proto                = AF_INET,
        .l4proto                = IPPROTO_DCCP,
-       .pkt_to_tuple           = dccp_pkt_to_tuple,
        .new                    = dccp_new,
        .packet                 = dccp_packet,
        .get_timeouts           = dccp_get_timeouts,
 const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 = {
        .l3proto                = AF_INET6,
        .l4proto                = IPPROTO_DCCP,
-       .pkt_to_tuple           = dccp_pkt_to_tuple,
        .new                    = dccp_new,
        .packet                 = dccp_packet,
        .get_timeouts           = dccp_get_timeouts,
 
        return &net->ct.nf_ct_proto.sctp;
 }
 
-static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
-                             struct net *net, struct nf_conntrack_tuple *tuple)
-{
-       const struct sctphdr *hp;
-       struct sctphdr _hdr;
-
-       /* Actually only need first 4 bytes to get ports. */
-       hp = skb_header_pointer(skb, dataoff, 4, &_hdr);
-       if (hp == NULL)
-               return false;
-
-       tuple->src.u.sctp.port = hp->source;
-       tuple->dst.u.sctp.port = hp->dest;
-       return true;
-}
-
 #ifdef CONFIG_NF_CONNTRACK_PROCFS
 /* Print out the private part of the conntrack. */
 static void sctp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
 const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = {
        .l3proto                = PF_INET,
        .l4proto                = IPPROTO_SCTP,
-       .pkt_to_tuple           = sctp_pkt_to_tuple,
 #ifdef CONFIG_NF_CONNTRACK_PROCFS
        .print_conntrack        = sctp_print_conntrack,
 #endif
 const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = {
        .l3proto                = PF_INET6,
        .l4proto                = IPPROTO_SCTP,
-       .pkt_to_tuple           = sctp_pkt_to_tuple,
 #ifdef CONFIG_NF_CONNTRACK_PROCFS
        .print_conntrack        = sctp_print_conntrack,
 #endif
 
        return &net->ct.nf_ct_proto.tcp;
 }
 
-static bool tcp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
-                            struct net *net, struct nf_conntrack_tuple *tuple)
-{
-       const struct tcphdr *hp;
-       struct tcphdr _hdr;
-
-       /* Actually only need first 4 bytes to get ports. */
-       hp = skb_header_pointer(skb, dataoff, 4, &_hdr);
-       if (hp == NULL)
-               return false;
-
-       tuple->src.u.tcp.port = hp->source;
-       tuple->dst.u.tcp.port = hp->dest;
-
-       return true;
-}
-
 #ifdef CONFIG_NF_CONNTRACK_PROCFS
 /* Print out the private part of the conntrack. */
 static void tcp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
 {
        .l3proto                = PF_INET,
        .l4proto                = IPPROTO_TCP,
-       .pkt_to_tuple           = tcp_pkt_to_tuple,
 #ifdef CONFIG_NF_CONNTRACK_PROCFS
        .print_conntrack        = tcp_print_conntrack,
 #endif
 {
        .l3proto                = PF_INET6,
        .l4proto                = IPPROTO_TCP,
-       .pkt_to_tuple           = tcp_pkt_to_tuple,
 #ifdef CONFIG_NF_CONNTRACK_PROCFS
        .print_conntrack        = tcp_print_conntrack,
 #endif
 
        return &net->ct.nf_ct_proto.udp;
 }
 
-static bool udp_pkt_to_tuple(const struct sk_buff *skb,
-                            unsigned int dataoff,
-                            struct net *net,
-                            struct nf_conntrack_tuple *tuple)
-{
-       const struct udphdr *hp;
-       struct udphdr _hdr;
-
-       /* Actually only need first 4 bytes to get ports. */
-       hp = skb_header_pointer(skb, dataoff, 4, &_hdr);
-       if (hp == NULL)
-               return false;
-
-       tuple->src.u.udp.port = hp->source;
-       tuple->dst.u.udp.port = hp->dest;
-
-       return true;
-}
-
 static unsigned int *udp_get_timeouts(struct net *net)
 {
        return udp_pernet(net)->timeouts;
        .l3proto                = PF_INET,
        .l4proto                = IPPROTO_UDP,
        .allow_clash            = true,
-       .pkt_to_tuple           = udp_pkt_to_tuple,
        .packet                 = udp_packet,
        .get_timeouts           = udp_get_timeouts,
        .new                    = udp_new,
        .l3proto                = PF_INET,
        .l4proto                = IPPROTO_UDPLITE,
        .allow_clash            = true,
-       .pkt_to_tuple           = udp_pkt_to_tuple,
        .packet                 = udp_packet,
        .get_timeouts           = udp_get_timeouts,
        .new                    = udp_new,
        .l3proto                = PF_INET6,
        .l4proto                = IPPROTO_UDP,
        .allow_clash            = true,
-       .pkt_to_tuple           = udp_pkt_to_tuple,
        .packet                 = udp_packet,
        .get_timeouts           = udp_get_timeouts,
        .new                    = udp_new,
        .l3proto                = PF_INET6,
        .l4proto                = IPPROTO_UDPLITE,
        .allow_clash            = true,
-       .pkt_to_tuple           = udp_pkt_to_tuple,
        .packet                 = udp_packet,
        .get_timeouts           = udp_get_timeouts,
        .new                    = udp_new,