aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2008-06-19 19:22:28 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-19 19:22:28 -0400
commit4497b0763cb1afae463f5e144c28b5d806e28b60 (patch)
tree3e86c53b5eb461eac7523885e43f36033cc03968
parent0187bdfb05674147774ca79a79942537f3ad54bd (diff)
net: Discard and warn about LRO'd skbs received for forwarding
Add skb_warn_if_lro() to test whether an skb was received with LRO and warn if so. Change br_forward(), ip_forward() and ip6_forward() to call it) and discard the skb if it returns true. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/skbuff.h14
-rw-r--r--net/bridge/br_forward.c2
-rw-r--r--net/core/skbuff.c8
-rw-r--r--net/ipv4/ip_forward.c3
-rw-r--r--net/ipv6/ip6_output.c3
5 files changed, 29 insertions, 1 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 299ec4b31412..2220b9e2dab0 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1702,6 +1702,20 @@ static inline int skb_is_gso_v6(const struct sk_buff *skb)
1702 return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6; 1702 return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6;
1703} 1703}
1704 1704
1705extern void __skb_warn_lro_forwarding(const struct sk_buff *skb);
1706
1707static inline bool skb_warn_if_lro(const struct sk_buff *skb)
1708{
1709 /* LRO sets gso_size but not gso_type, whereas if GSO is really
1710 * wanted then gso_type will be set. */
1711 struct skb_shared_info *shinfo = skb_shinfo(skb);
1712 if (shinfo->gso_size != 0 && unlikely(shinfo->gso_type == 0)) {
1713 __skb_warn_lro_forwarding(skb);
1714 return true;
1715 }
1716 return false;
1717}
1718
1705static inline void skb_forward_csum(struct sk_buff *skb) 1719static inline void skb_forward_csum(struct sk_buff *skb)
1706{ 1720{
1707 /* Unfortunately we don't support this one. Any brave souls? */ 1721 /* Unfortunately we don't support this one. Any brave souls? */
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 512645727f51..bdd9ccea17ce 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -89,7 +89,7 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
89/* called with rcu_read_lock */ 89/* called with rcu_read_lock */
90void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) 90void br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
91{ 91{
92 if (should_deliver(to, skb)) { 92 if (!skb_warn_if_lro(skb) && should_deliver(to, skb)) {
93 __br_forward(to, skb); 93 __br_forward(to, skb);
94 return; 94 return;
95 } 95 }
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3e18f8525e82..2df012be973d 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2583,6 +2583,13 @@ bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off)
2583 return true; 2583 return true;
2584} 2584}
2585 2585
2586void __skb_warn_lro_forwarding(const struct sk_buff *skb)
2587{
2588 if (net_ratelimit())
2589 pr_warning("%s: received packets cannot be forwarded"
2590 " while LRO is enabled\n", skb->dev->name);
2591}
2592
2586EXPORT_SYMBOL(___pskb_trim); 2593EXPORT_SYMBOL(___pskb_trim);
2587EXPORT_SYMBOL(__kfree_skb); 2594EXPORT_SYMBOL(__kfree_skb);
2588EXPORT_SYMBOL(kfree_skb); 2595EXPORT_SYMBOL(kfree_skb);
@@ -2616,6 +2623,7 @@ EXPORT_SYMBOL(skb_seq_read);
2616EXPORT_SYMBOL(skb_abort_seq_read); 2623EXPORT_SYMBOL(skb_abort_seq_read);
2617EXPORT_SYMBOL(skb_find_text); 2624EXPORT_SYMBOL(skb_find_text);
2618EXPORT_SYMBOL(skb_append_datato_frags); 2625EXPORT_SYMBOL(skb_append_datato_frags);
2626EXPORT_SYMBOL(__skb_warn_lro_forwarding);
2619 2627
2620EXPORT_SYMBOL_GPL(skb_to_sgvec); 2628EXPORT_SYMBOL_GPL(skb_to_sgvec);
2621EXPORT_SYMBOL_GPL(skb_cow_data); 2629EXPORT_SYMBOL_GPL(skb_cow_data);
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index 37d36a3f33cd..da14725916d3 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -56,6 +56,9 @@ int ip_forward(struct sk_buff *skb)
56 struct rtable *rt; /* Route we use */ 56 struct rtable *rt; /* Route we use */
57 struct ip_options * opt = &(IPCB(skb)->opt); 57 struct ip_options * opt = &(IPCB(skb)->opt);
58 58
59 if (skb_warn_if_lro(skb))
60 goto drop;
61
59 if (!xfrm4_policy_check(NULL, XFRM_POLICY_FWD, skb)) 62 if (!xfrm4_policy_check(NULL, XFRM_POLICY_FWD, skb))
60 goto drop; 63 goto drop;
61 64
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 40a2813a63d1..fd7cd1bfe151 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -407,6 +407,9 @@ int ip6_forward(struct sk_buff *skb)
407 if (ipv6_devconf.forwarding == 0) 407 if (ipv6_devconf.forwarding == 0)
408 goto error; 408 goto error;
409 409
410 if (skb_warn_if_lro(skb))
411 goto drop;
412
410 if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) { 413 if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) {
411 IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); 414 IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
412 goto drop; 415 goto drop;