aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorJerry Chu <hkchu@google.com>2013-12-11 23:53:45 -0500
committerDavid S. Miller <davem@davemloft.net>2013-12-12 13:47:53 -0500
commit299603e8370a93dd5d8e8d800f0dff1ce2c53d36 (patch)
tree2a10106aabe88c278a0cd02b93af1add04f5ffcc /net/core/dev.c
parenta46dc748caea185d4d0978280a1af0112bf6a8f8 (diff)
net-gro: Prepare GRO stack for the upcoming tunneling support
This patch modifies the GRO stack to avoid the use of "network_header" and associated macros like ip_hdr() and ipv6_hdr() in order to allow an arbitary number of IP hdrs (v4 or v6) to be used in the encapsulation chain. This lays the foundation for various IP tunneling support (IP-in-IP, GRE, VXLAN, SIT,...) to be added later. With this patch, the GRO stack traversing now is mostly based on skb_gro_offset rather than special hdr offsets saved in skb (e.g., skb->network_header). As a result all but the top layer (i.e., the the transport layer) must have hdrs of the same length in order for a pkt to be considered for aggregation. Therefore when adding a new encap layer (e.g., for tunneling), one must check and skip flows (e.g., by setting NAPI_GRO_CB(p)->same_flow to 0) that have a different hdr length. Note that unlike the network header, the transport header can and will continue to be set by the GRO code since there will be at most one "transport layer" in the encap chain. Signed-off-by: H.K. Jerry Chu <hkchu@google.com> Suggested-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c76
1 files changed, 25 insertions, 51 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 355df36360b4..c95d664b2b42 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3752,7 +3752,7 @@ static int napi_gro_complete(struct sk_buff *skb)
3752 if (ptype->type != type || !ptype->callbacks.gro_complete) 3752 if (ptype->type != type || !ptype->callbacks.gro_complete)
3753 continue; 3753 continue;
3754 3754
3755 err = ptype->callbacks.gro_complete(skb); 3755 err = ptype->callbacks.gro_complete(skb, 0);
3756 break; 3756 break;
3757 } 3757 }
3758 rcu_read_unlock(); 3758 rcu_read_unlock();
@@ -3818,6 +3818,23 @@ static void gro_list_prepare(struct napi_struct *napi, struct sk_buff *skb)
3818 } 3818 }
3819} 3819}
3820 3820
3821static void skb_gro_reset_offset(struct sk_buff *skb)
3822{
3823 const struct skb_shared_info *pinfo = skb_shinfo(skb);
3824 const skb_frag_t *frag0 = &pinfo->frags[0];
3825
3826 NAPI_GRO_CB(skb)->data_offset = 0;
3827 NAPI_GRO_CB(skb)->frag0 = NULL;
3828 NAPI_GRO_CB(skb)->frag0_len = 0;
3829
3830 if (skb_mac_header(skb) == skb_tail_pointer(skb) &&
3831 pinfo->nr_frags &&
3832 !PageHighMem(skb_frag_page(frag0))) {
3833 NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0);
3834 NAPI_GRO_CB(skb)->frag0_len = skb_frag_size(frag0);
3835 }
3836}
3837
3821static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) 3838static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
3822{ 3839{
3823 struct sk_buff **pp = NULL; 3840 struct sk_buff **pp = NULL;
@@ -3833,6 +3850,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
3833 if (skb_is_gso(skb) || skb_has_frag_list(skb)) 3850 if (skb_is_gso(skb) || skb_has_frag_list(skb))
3834 goto normal; 3851 goto normal;
3835 3852
3853 skb_gro_reset_offset(skb);
3836 gro_list_prepare(napi, skb); 3854 gro_list_prepare(napi, skb);
3837 3855
3838 rcu_read_lock(); 3856 rcu_read_lock();
@@ -3938,27 +3956,8 @@ static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
3938 return ret; 3956 return ret;
3939} 3957}
3940 3958
3941static void skb_gro_reset_offset(struct sk_buff *skb)
3942{
3943 const struct skb_shared_info *pinfo = skb_shinfo(skb);
3944 const skb_frag_t *frag0 = &pinfo->frags[0];
3945
3946 NAPI_GRO_CB(skb)->data_offset = 0;
3947 NAPI_GRO_CB(skb)->frag0 = NULL;
3948 NAPI_GRO_CB(skb)->frag0_len = 0;
3949
3950 if (skb_mac_header(skb) == skb_tail_pointer(skb) &&
3951 pinfo->nr_frags &&
3952 !PageHighMem(skb_frag_page(frag0))) {
3953 NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0);
3954 NAPI_GRO_CB(skb)->frag0_len = skb_frag_size(frag0);
3955 }
3956}
3957
3958gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) 3959gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
3959{ 3960{
3960 skb_gro_reset_offset(skb);
3961
3962 return napi_skb_finish(dev_gro_receive(napi, skb), skb); 3961 return napi_skb_finish(dev_gro_receive(napi, skb), skb);
3963} 3962}
3964EXPORT_SYMBOL(napi_gro_receive); 3963EXPORT_SYMBOL(napi_gro_receive);
@@ -3992,12 +3991,7 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *
3992{ 3991{
3993 switch (ret) { 3992 switch (ret) {
3994 case GRO_NORMAL: 3993 case GRO_NORMAL:
3995 case GRO_HELD: 3994 if (netif_receive_skb(skb))
3996 skb->protocol = eth_type_trans(skb, skb->dev);
3997
3998 if (ret == GRO_HELD)
3999 skb_gro_pull(skb, -ETH_HLEN);
4000 else if (netif_receive_skb(skb))
4001 ret = GRO_DROP; 3995 ret = GRO_DROP;
4002 break; 3996 break;
4003 3997
@@ -4006,6 +4000,7 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *
4006 napi_reuse_skb(napi, skb); 4000 napi_reuse_skb(napi, skb);
4007 break; 4001 break;
4008 4002
4003 case GRO_HELD:
4009 case GRO_MERGED: 4004 case GRO_MERGED:
4010 break; 4005 break;
4011 } 4006 }
@@ -4016,36 +4011,15 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *
4016static struct sk_buff *napi_frags_skb(struct napi_struct *napi) 4011static struct sk_buff *napi_frags_skb(struct napi_struct *napi)
4017{ 4012{
4018 struct sk_buff *skb = napi->skb; 4013 struct sk_buff *skb = napi->skb;
4019 struct ethhdr *eth;
4020 unsigned int hlen;
4021 unsigned int off;
4022 4014
4023 napi->skb = NULL; 4015 napi->skb = NULL;
4024 4016
4025 skb_reset_mac_header(skb); 4017 if (unlikely(!pskb_may_pull(skb, sizeof(struct ethhdr)))) {
4026 skb_gro_reset_offset(skb); 4018 napi_reuse_skb(napi, skb);
4027 4019 return NULL;
4028 off = skb_gro_offset(skb);
4029 hlen = off + sizeof(*eth);
4030 eth = skb_gro_header_fast(skb, off);
4031 if (skb_gro_header_hard(skb, hlen)) {
4032 eth = skb_gro_header_slow(skb, hlen, off);
4033 if (unlikely(!eth)) {
4034 napi_reuse_skb(napi, skb);
4035 skb = NULL;
4036 goto out;
4037 }
4038 } 4020 }
4021 skb->protocol = eth_type_trans(skb, skb->dev);
4039 4022
4040 skb_gro_pull(skb, sizeof(*eth));
4041
4042 /*
4043 * This works because the only protocols we care about don't require
4044 * special handling. We'll fix it up properly at the end.
4045 */
4046 skb->protocol = eth->h_proto;
4047
4048out:
4049 return skb; 4023 return skb;
4050} 4024}
4051 4025