From 50d17b364f76c3c6b9a5c609717366836683b243 Mon Sep 17 00:00:00 2001 From: Dan Duval Date: Thu, 16 Jun 2016 18:45:07 -0400 Subject: [PATCH] Revert "net: preserve IP control block during GSO segmentation" Orabug: 23522263 This reverts commit a9e889c735eef731df3fce53fb997277f3b0b498. Yuval Shaia and team discovered that the aforementioned commit resulted in a substantial (900-to-1) performance loss on a TCP bandwidth test over IPoIB. Upstream is aware of the problem but there is currently no solution in hand, so just revert the offending commmit. Note that the original commit purports to fix a kernel crash, but so far we haven't seen the crash. Signed-off-by: Dan Duval Signed-off-by: Yuval Shaia Signed-off-by: Ajaykumar Hotchandani Tested-by: Rose Wang --- include/linux/skbuff.h | 3 +-- net/core/dev.c | 5 ----- net/ipv4/ip_output.c | 1 - net/openvswitch/datapath.c | 5 ++++- net/xfrm/xfrm_output.c | 2 -- 5 files changed, 5 insertions(+), 11 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 1f17abe23725..4307e20a4a4a 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -3320,8 +3320,7 @@ struct skb_gso_cb { int encap_level; __u16 csum_start; }; -#define SKB_SGO_CB_OFFSET 32 -#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)((skb)->cb + SKB_SGO_CB_OFFSET)) +#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)(skb)->cb) static inline int skb_tnl_header_len(const struct sk_buff *inner_skb) { diff --git a/net/core/dev.c b/net/core/dev.c index 185a3398c651..a42b232805a5 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2479,8 +2479,6 @@ static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path) * * It may return NULL if the skb requires no segmentation. This is * only possible when GSO is used for verifying header integrity. - * - * Segmentation preserves SKB_SGO_CB_OFFSET bytes of previous skb cb. */ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, netdev_features_t features, bool tx_path) @@ -2495,9 +2493,6 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, return ERR_PTR(err); } - BUILD_BUG_ON(SKB_SGO_CB_OFFSET + - sizeof(*SKB_GSO_CB(skb)) > sizeof(skb->cb)); - SKB_GSO_CB(skb)->mac_offset = skb_headroom(skb); SKB_GSO_CB(skb)->encap_level = 0; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 51573f8a39bc..fe16f418e775 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -235,7 +235,6 @@ static int ip_finish_output_gso(struct sock *sk, struct sk_buff *skb) * from host network stack. */ features = netif_skb_features(skb); - BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_SGO_CB_OFFSET); segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK); if (IS_ERR_OR_NULL(segs)) { kfree_skb(skb); diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index b3fe02a2339e..27e14962b504 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -337,10 +337,12 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, unsigned short gso_type = skb_shinfo(skb)->gso_type; struct sw_flow_key later_key; struct sk_buff *segs, *nskb; + struct ovs_skb_cb ovs_cb; int err; - BUILD_BUG_ON(sizeof(*OVS_CB(skb)) > SKB_SGO_CB_OFFSET); + ovs_cb = *OVS_CB(skb); segs = __skb_gso_segment(skb, NETIF_F_SG, false); + *OVS_CB(skb) = ovs_cb; if (IS_ERR(segs)) return PTR_ERR(segs); if (segs == NULL) @@ -358,6 +360,7 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, /* Queue all of the segments. */ skb = segs; do { + *OVS_CB(skb) = ovs_cb; if (gso_type & SKB_GSO_UDP && skb != segs) key = &later_key; diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 5097dce5b916..fbcedbe33190 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -153,8 +153,6 @@ static int xfrm_output_gso(struct sock *sk, struct sk_buff *skb) { struct sk_buff *segs; - BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_SGO_CB_OFFSET); - BUILD_BUG_ON(sizeof(*IP6CB(skb)) > SKB_SGO_CB_OFFSET); segs = skb_gso_segment(skb, 0); kfree_skb(skb); if (IS_ERR(segs)) -- 2.50.1