struct net_device *,
                                         struct packet_type *,
                                         struct net_device *);
-       struct sk_buff          *(*gso_segment)(struct sk_buff *skb,
-                                               netdev_features_t features);
-       int                     (*gso_send_check)(struct sk_buff *skb);
-       struct sk_buff          **(*gro_receive)(struct sk_buff **head,
-                                              struct sk_buff *skb);
-       int                     (*gro_complete)(struct sk_buff *skb);
        bool                    (*id_match)(struct packet_type *ptype,
                                            struct sock *sk);
        void                    *af_packet_priv;
 
        netdev_features_t features)
 {
        struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
-       struct packet_type *ptype;
+       struct packet_offload *ptype;
        __be16 type = skb->protocol;
        int vlan_depth = ETH_HLEN;
        int err;
        }
 
        rcu_read_lock();
-       list_for_each_entry_rcu(ptype,
-                       &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
-               if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
+       list_for_each_entry_rcu(ptype, &offload_base, list) {
+               if (ptype->type == type && ptype->gso_segment) {
                        if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) {
                                err = ptype->gso_send_check(skb);
                                segs = ERR_PTR(err);
 
 static int napi_gro_complete(struct sk_buff *skb)
 {
-       struct packet_type *ptype;
+       struct packet_offload *ptype;
        __be16 type = skb->protocol;
-       struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
+       struct list_head *head = &offload_base;
        int err = -ENOENT;
 
        if (NAPI_GRO_CB(skb)->count == 1) {
 
        rcu_read_lock();
        list_for_each_entry_rcu(ptype, head, list) {
-               if (ptype->type != type || ptype->dev || !ptype->gro_complete)
+               if (ptype->type != type || !ptype->gro_complete)
                        continue;
 
                err = ptype->gro_complete(skb);
 enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
        struct sk_buff **pp = NULL;
-       struct packet_type *ptype;
+       struct packet_offload *ptype;
        __be16 type = skb->protocol;
-       struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
+       struct list_head *head = &offload_base;
        int same_flow;
        int mac_len;
        enum gro_result ret;
 
        rcu_read_lock();
        list_for_each_entry_rcu(ptype, head, list) {
-               if (ptype->type != type || ptype->dev || !ptype->gro_receive)
+               if (ptype->type != type || !ptype->gro_receive)
                        continue;
 
                skb_set_network_header(skb, skb_gro_offset(skb));
 
 static struct packet_type ip_packet_type __read_mostly = {
        .type = cpu_to_be16(ETH_P_IP),
        .func = ip_rcv,
+};
+
+static struct packet_offload ip_packet_offload __read_mostly = {
+       .type = cpu_to_be16(ETH_P_IP),
        .gso_send_check = inet_gso_send_check,
        .gso_segment = inet_gso_segment,
        .gro_receive = inet_gro_receive,
 
        ipfrag_init();
 
+       dev_add_offload(&ip_packet_offload);
        dev_add_pack(&ip_packet_type);
 
        rc = 0;
 
 static struct packet_type ipv6_packet_type __read_mostly = {
        .type = cpu_to_be16(ETH_P_IPV6),
        .func = ipv6_rcv,
+};
+
+static struct packet_offload ipv6_packet_offload __read_mostly = {
+       .type = cpu_to_be16(ETH_P_IPV6),
        .gso_send_check = ipv6_gso_send_check,
        .gso_segment = ipv6_gso_segment,
        .gro_receive = ipv6_gro_receive,
 
 static int __init ipv6_packet_init(void)
 {
+       dev_add_offload(&ipv6_packet_offload);
        dev_add_pack(&ipv6_packet_type);
        return 0;
 }
 static void ipv6_packet_cleanup(void)
 {
        dev_remove_pack(&ipv6_packet_type);
+       dev_remove_offload(&ipv6_packet_offload);
 }
 
 static int __net_init ipv6_init_mibs(struct net *net)