mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
net: use indirect call wrappers at GRO transport layer
This avoids an indirect call in the receive path for TCP and UDP packets. TCP takes precedence on UDP, so that we have a single additional conditional in the common case. When IPV6 is build as module, all gro symbols except UDPv6 are builtin, while the latter belong to the ipv6 module, so we need some special care. v1 -> v2: - adapted to INDIRECT_CALL_ changes v2 -> v3: - fix build issue with CONFIG_IPV6=m Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: David S. Miller <[email protected]>
This commit is contained in:
parent
aaa5d90b39
commit
028e0a4766
7 changed files with 61 additions and 15 deletions
|
|
@ -1385,6 +1385,10 @@ out:
|
|||
}
|
||||
EXPORT_SYMBOL(inet_gso_segment);
|
||||
|
||||
INDIRECT_CALLABLE_DECLARE(struct sk_buff *tcp4_gro_receive(struct list_head *,
|
||||
struct sk_buff *));
|
||||
INDIRECT_CALLABLE_DECLARE(struct sk_buff *udp4_gro_receive(struct list_head *,
|
||||
struct sk_buff *));
|
||||
struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb)
|
||||
{
|
||||
const struct net_offload *ops;
|
||||
|
|
@ -1494,7 +1498,8 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb)
|
|||
skb_gro_pull(skb, sizeof(*iph));
|
||||
skb_set_transport_header(skb, skb_gro_offset(skb));
|
||||
|
||||
pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
|
||||
pp = indirect_call_gro_receive(tcp4_gro_receive, udp4_gro_receive,
|
||||
ops->callbacks.gro_receive, head, skb);
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
|
|
@ -1556,6 +1561,8 @@ int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
INDIRECT_CALLABLE_DECLARE(int tcp4_gro_complete(struct sk_buff *, int));
|
||||
INDIRECT_CALLABLE_DECLARE(int udp4_gro_complete(struct sk_buff *, int));
|
||||
int inet_gro_complete(struct sk_buff *skb, int nhoff)
|
||||
{
|
||||
__be16 newlen = htons(skb->len - nhoff);
|
||||
|
|
@ -1581,7 +1588,9 @@ int inet_gro_complete(struct sk_buff *skb, int nhoff)
|
|||
* because any hdr with option will have been flushed in
|
||||
* inet_gro_receive().
|
||||
*/
|
||||
err = ops->callbacks.gro_complete(skb, nhoff + sizeof(*iph));
|
||||
err = INDIRECT_CALL_2(ops->callbacks.gro_complete,
|
||||
tcp4_gro_complete, udp4_gro_complete,
|
||||
skb, nhoff + sizeof(*iph));
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
* TCPv4 GSO/GRO support
|
||||
*/
|
||||
|
||||
#include <linux/indirect_call_wrapper.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/protocol.h>
|
||||
|
|
@ -305,7 +306,8 @@ int tcp_gro_complete(struct sk_buff *skb)
|
|||
}
|
||||
EXPORT_SYMBOL(tcp_gro_complete);
|
||||
|
||||
static struct sk_buff *tcp4_gro_receive(struct list_head *head, struct sk_buff *skb)
|
||||
INDIRECT_CALLABLE_SCOPE
|
||||
struct sk_buff *tcp4_gro_receive(struct list_head *head, struct sk_buff *skb)
|
||||
{
|
||||
/* Don't bother verifying checksum if we're going to flush anyway. */
|
||||
if (!NAPI_GRO_CB(skb)->flush &&
|
||||
|
|
@ -318,7 +320,7 @@ static struct sk_buff *tcp4_gro_receive(struct list_head *head, struct sk_buff *
|
|||
return tcp_gro_receive(head, skb);
|
||||
}
|
||||
|
||||
static int tcp4_gro_complete(struct sk_buff *skb, int thoff)
|
||||
INDIRECT_CALLABLE_SCOPE int tcp4_gro_complete(struct sk_buff *skb, int thoff)
|
||||
{
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
struct tcphdr *th = tcp_hdr(skb);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <net/udp.h>
|
||||
#include <net/protocol.h>
|
||||
#include <net/inet_common.h>
|
||||
|
||||
static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
|
||||
netdev_features_t features,
|
||||
|
|
@ -451,8 +452,8 @@ out_unlock:
|
|||
}
|
||||
EXPORT_SYMBOL(udp_gro_receive);
|
||||
|
||||
static struct sk_buff *udp4_gro_receive(struct list_head *head,
|
||||
struct sk_buff *skb)
|
||||
INDIRECT_CALLABLE_SCOPE
|
||||
struct sk_buff *udp4_gro_receive(struct list_head *head, struct sk_buff *skb)
|
||||
{
|
||||
struct udphdr *uh = udp_gro_udphdr(skb);
|
||||
|
||||
|
|
@ -525,7 +526,7 @@ int udp_gro_complete(struct sk_buff *skb, int nhoff,
|
|||
}
|
||||
EXPORT_SYMBOL(udp_gro_complete);
|
||||
|
||||
static int udp4_gro_complete(struct sk_buff *skb, int nhoff)
|
||||
INDIRECT_CALLABLE_SCOPE int udp4_gro_complete(struct sk_buff *skb, int nhoff)
|
||||
{
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
struct udphdr *uh = (struct udphdr *)(skb->data + nhoff);
|
||||
|
|
|
|||
Loading…
Reference in a new issue