From 2fd936d51bae2760a940e6a341cd87af1881a1ff Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 4 Aug 2014 21:54:31 -0700 Subject: [PATCH] 3.4-stable patches added patches: revert-net-ip-ipv6-handle-gso-skbs-in-forwarding-path.patch --- ...6-handle-gso-skbs-in-forwarding-path.patch | 167 ++++++++++++++++++ queue-3.4/series | 1 + 2 files changed, 168 insertions(+) create mode 100644 queue-3.4/revert-net-ip-ipv6-handle-gso-skbs-in-forwarding-path.patch diff --git a/queue-3.4/revert-net-ip-ipv6-handle-gso-skbs-in-forwarding-path.patch b/queue-3.4/revert-net-ip-ipv6-handle-gso-skbs-in-forwarding-path.patch new file mode 100644 index 00000000000..62eabe0f4d0 --- /dev/null +++ b/queue-3.4/revert-net-ip-ipv6-handle-gso-skbs-in-forwarding-path.patch @@ -0,0 +1,167 @@ +From foo@baz Mon Aug 4 21:42:10 PDT 2014 +Date: Mon, 04 Aug 2014 21:42:10 -0700 +To: Greg KH +From: Greg Kroah-Hartman +Subject: Revert: "net: ip, ipv6: handle gso skbs in forwarding path" + +This reverts commit 29a3cd46644ec8098dbe1c12f89643b5c11831a9 which is +commit fe6cc55f3a9a053482a76f5a6b2257cee51b4663 upstream. + +Cc: Herbert Xu +Cc: Marcelo Ricardo Leitner +Cc: Florian Westphal +Cc: David S. Miller +Cc: Thomas Jarosch +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/skbuff.h | 17 ------------ + net/ipv4/ip_forward.c | 68 +------------------------------------------------ + net/ipv6/ip6_output.c | 13 --------- + 3 files changed, 3 insertions(+), 95 deletions(-) + +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -2608,22 +2608,5 @@ static inline bool skb_is_recycleable(co + + return true; + } +- +-/** +- * skb_gso_network_seglen - Return length of individual segments of a gso packet +- * +- * @skb: GSO skb +- * +- * skb_gso_network_seglen is used to determine the real size of the +- * individual segments, including Layer3 (IP, IPv6) and L4 headers (TCP/UDP). +- * +- * The MAC/L2 header is not accounted for. +- */ +-static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb) +-{ +- unsigned int hdr_len = skb_transport_header(skb) - +- skb_network_header(skb); +- return hdr_len + skb_gso_transport_seglen(skb); +-} + #endif /* __KERNEL__ */ + #endif /* _LINUX_SKBUFF_H */ +--- a/net/ipv4/ip_forward.c ++++ b/net/ipv4/ip_forward.c +@@ -39,68 +39,6 @@ + #include + #include + +-static bool ip_may_fragment(const struct sk_buff *skb) +-{ +- return unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) || +- skb->local_df; +-} +- +-static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) +-{ +- if (skb->len <= mtu) +- return false; +- +- if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu) +- return false; +- +- return true; +-} +- +-static bool ip_gso_exceeds_dst_mtu(const struct sk_buff *skb) +-{ +- unsigned int mtu; +- +- if (skb->local_df || !skb_is_gso(skb)) +- return false; +- +- mtu = dst_mtu(skb_dst(skb)); +- +- /* if seglen > mtu, do software segmentation for IP fragmentation on +- * output. DF bit cannot be set since ip_forward would have sent +- * icmp error. +- */ +- return skb_gso_network_seglen(skb) > mtu; +-} +- +-/* called if GSO skb needs to be fragmented on forward */ +-static int ip_forward_finish_gso(struct sk_buff *skb) +-{ +- struct sk_buff *segs; +- int ret = 0; +- +- segs = skb_gso_segment(skb, 0); +- if (IS_ERR(segs)) { +- kfree_skb(skb); +- return -ENOMEM; +- } +- +- consume_skb(skb); +- +- do { +- struct sk_buff *nskb = segs->next; +- int err; +- +- segs->next = NULL; +- err = dst_output(segs); +- +- if (err && ret == 0) +- ret = err; +- segs = nskb; +- } while (segs); +- +- return ret; +-} +- + static int ip_forward_finish(struct sk_buff *skb) + { + struct ip_options * opt = &(IPCB(skb)->opt); +@@ -110,9 +48,6 @@ static int ip_forward_finish(struct sk_b + if (unlikely(opt->optlen)) + ip_forward_options(skb); + +- if (ip_gso_exceeds_dst_mtu(skb)) +- return ip_forward_finish_gso(skb); +- + return dst_output(skb); + } + +@@ -152,7 +87,8 @@ int ip_forward(struct sk_buff *skb) + if (opt->is_strictroute && opt->nexthop != rt->rt_gateway) + goto sr_failed; + +- if (!ip_may_fragment(skb) && ip_exceeds_mtu(skb, dst_mtu(&rt->dst))) { ++ if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) && ++ (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) { + IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(dst_mtu(&rt->dst))); +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -382,17 +382,6 @@ static inline int ip6_forward_finish(str + return dst_output(skb); + } + +-static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu) +-{ +- if (skb->len <= mtu || skb->local_df) +- return false; +- +- if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu) +- return false; +- +- return true; +-} +- + int ip6_forward(struct sk_buff *skb) + { + struct dst_entry *dst = skb_dst(skb); +@@ -514,7 +503,7 @@ int ip6_forward(struct sk_buff *skb) + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + +- if (ip6_pkt_too_big(skb, mtu)) { ++ if (skb->len > mtu && !skb_is_gso(skb)) { + /* Again, force OUTPUT device used as source address */ + skb->dev = dst->dev; + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); diff --git a/queue-3.4/series b/queue-3.4/series index 032e06be286..2a3035c4c8b 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -11,3 +11,4 @@ x86-espfix-fix-broken-header-guard.patch x86-espfix-make-espfix64-a-kconfig-option-fix-uml.patch x86-espfix-make-it-possible-to-disable-16-bit-support.patch x86_64-entry-xen-do-not-invoke-espfix64-on-xen.patch +revert-net-ip-ipv6-handle-gso-skbs-in-forwarding-path.patch -- 2.47.3