@@ -467,7 +467,7 @@ static struct sk_buff *geneve_gro_receive(struct sock *sk,
type = gh->proto_type;
rcu_read_lock();
- ptype = gro_find_receive_by_type(type);
+ ptype = net_gro_receive(dev_offloads, type);
if (!ptype)
goto out_unlock;
@@ -3556,7 +3556,6 @@ gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb);
void napi_gro_flush(struct napi_struct *napi, bool flush_old);
struct sk_buff *napi_get_frags(struct napi_struct *napi);
gro_result_t napi_gro_frags(struct napi_struct *napi);
-struct packet_offload *gro_find_receive_by_type(__be16 type);
extern const struct net_offload __rcu *dev_offloads[256];
@@ -3568,6 +3567,19 @@ static inline u8 net_offload_from_type(u16 type)
return type & 0xFF;
}
+static inline const struct net_offload *
+net_gro_receive(const struct net_offload __rcu **offs, u16 type)
+{
+ const struct net_offload *off;
+
+ off = rcu_dereference(offs[net_offload_from_type(type)]);
+ if (off && off->callbacks.gro_receive &&
+ (!off->type || off->type == type))
+ return off;
+ else
+ return NULL;
+}
+
static inline int net_gro_complete(const struct net_offload __rcu **offs,
u16 type, struct sk_buff *skb, int nhoff)
{
@@ -670,7 +670,7 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head,
type = vhdr->h_vlan_encapsulated_proto;
rcu_read_lock();
- ptype = gro_find_receive_by_type(type);
+ ptype = net_gro_receive(dev_offloads, type);
if (!ptype)
goto out_unlock;
@@ -5382,7 +5382,7 @@ static void gro_flush_oldest(struct list_head *head)
static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
{
u32 hash = skb_get_hash_raw(skb) & (GRO_HASH_BUCKETS - 1);
- const struct packet_offload *ptype;
+ const struct net_offload *ops;
__be16 type = skb->protocol;
struct list_head *gro_head;
struct sk_buff *pp = NULL;
@@ -5396,8 +5396,8 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
gro_head = gro_list_prepare(napi, skb);
rcu_read_lock();
- ptype = dev_offloads[net_offload_from_type(type)];
- if (ptype && ptype->callbacks.gro_receive) {
+ ops = net_gro_receive(dev_offloads, type);
+ if (ops) {
skb_set_network_header(skb, skb_gro_offset(skb));
skb_reset_mac_len(skb);
NAPI_GRO_CB(skb)->same_flow = 0;
@@ -5425,7 +5425,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
NAPI_GRO_CB(skb)->csum_valid = 0;
}
- pp = ptype->callbacks.gro_receive(gro_head, skb);
+ pp = ops->callbacks.gro_receive(gro_head, skb);
rcu_read_unlock();
} else {
rcu_read_unlock();
@@ -5483,18 +5483,6 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
goto pull;
}
-struct packet_offload *gro_find_receive_by_type(__be16 type)
-{
- struct net_offload *off;
-
- off = (struct net_offload *) rcu_dereference(dev_offloads[type & 0xFF]);
- if (off && off->type == type && off->callbacks.gro_receive)
- return off;
- else
- return NULL;
-}
-EXPORT_SYMBOL(gro_find_receive_by_type);
-
static void napi_skb_free_stolen_head(struct sk_buff *skb)
{
skb_dst_drop(skb);
@@ -462,7 +462,7 @@ struct sk_buff *eth_gro_receive(struct list_head *head, struct sk_buff *skb)
type = eh->h_proto;
rcu_read_lock();
- ptype = gro_find_receive_by_type(type);
+ ptype = net_gro_receive(dev_offloads, type);
if (ptype == NULL) {
flush = 1;
goto out_unlock;
@@ -1409,8 +1409,8 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb)
proto = iph->protocol;
rcu_read_lock();
- ops = rcu_dereference(inet_offloads[proto]);
- if (!ops || !ops->callbacks.gro_receive)
+ ops = net_gro_receive(inet_offloads, proto);
+ if (!ops)
goto out_unlock;
if (*(u8 *)iph != 0x45)
@@ -246,8 +246,8 @@ static struct sk_buff *fou_gro_receive(struct sock *sk,
rcu_read_lock();
offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
- ops = rcu_dereference(offloads[proto]);
- if (!ops || !ops->callbacks.gro_receive)
+ ops = net_gro_receive(offloads, proto);
+ if (!ops)
goto out_unlock;
pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
@@ -428,8 +428,8 @@ static struct sk_buff *gue_gro_receive(struct sock *sk,
rcu_read_lock();
offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
- ops = rcu_dereference(offloads[proto]);
- if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive))
+ ops = net_gro_receive(offloads, proto);
+ if (WARN_ON_ONCE(!ops))
goto out_unlock;
pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
@@ -111,13 +111,13 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
static struct sk_buff *gre_gro_receive(struct list_head *head,
struct sk_buff *skb)
{
- struct sk_buff *pp = NULL;
- struct sk_buff *p;
const struct gre_base_hdr *greh;
+ const struct net_offload *ops;
unsigned int hlen, grehlen;
+ struct sk_buff *pp = NULL;
+ struct sk_buff *p;
unsigned int off;
int flush = 1;
- struct packet_offload *ptype;
__be16 type;
if (NAPI_GRO_CB(skb)->encap_mark)
@@ -154,8 +154,8 @@ static struct sk_buff *gre_gro_receive(struct list_head *head,
type = greh->protocol;
rcu_read_lock();
- ptype = gro_find_receive_by_type(type);
- if (!ptype)
+ ops = net_gro_receive(dev_offloads, type);
+ if (!ops)
goto out_unlock;
grehlen = GRE_HEADER_SECTION;
@@ -217,7 +217,7 @@ static struct sk_buff *gre_gro_receive(struct list_head *head,
/* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/
skb_gro_postpull_rcsum(skb, greh, grehlen);
- pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
+ pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
flush = 0;
out_unlock:
@@ -194,8 +194,8 @@ static struct sk_buff *ipv6_gro_receive(struct list_head *head,
rcu_read_lock();
proto = iph->nexthdr;
- ops = rcu_dereference(inet6_offloads[proto]);
- if (!ops || !ops->callbacks.gro_receive) {
+ ops = net_gro_receive(inet6_offloads, proto);
+ if (!ops) {
__pskb_pull(skb, skb_gro_offset(skb));
skb_gro_frag0_invalidate(skb);
proto = ipv6_gso_pull_exthdrs(skb, proto);
@@ -203,8 +203,8 @@ static struct sk_buff *ipv6_gro_receive(struct list_head *head,
skb_reset_transport_header(skb);
__skb_push(skb, skb_gro_offset(skb));
- ops = rcu_dereference(inet6_offloads[proto]);
- if (!ops || !ops->callbacks.gro_receive)
+ ops = net_gro_receive(inet6_offloads, proto);
+ if (!ops)
goto out_unlock;
iph = ipv6_hdr(skb);