aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Horman <horms@verge.net.au>2010-11-08 20:08:49 -0500
committerSimon Horman <horms@verge.net.au>2010-11-15 18:13:08 -0500
commit8f1b03a4c18e8f3f0801447b62330faa8ed3bb37 (patch)
treec5ee7d4e86df41fbb0a3782813629fc683fd9abf
parenta333e2ec05791bb866086274ac9749315900a0a6 (diff)
ipvs: allow transmit of GRO aggregated skbs
Attempt at allowing LVS to transmit skbs of greater than MTU length that have been aggregated by GRO and can thus be deaggregated by GSO. Cc: Julian Anastasov <ja@ssi.bg> Cc: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 50b131c28b85..fb2a445ddc59 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -407,7 +407,8 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
407 407
408 /* MTU checking */ 408 /* MTU checking */
409 mtu = dst_mtu(&rt->dst); 409 mtu = dst_mtu(&rt->dst);
410 if ((skb->len > mtu) && (iph->frag_off & htons(IP_DF))) { 410 if ((skb->len > mtu) && (iph->frag_off & htons(IP_DF)) &&
411 !skb_is_gso(skb)) {
411 ip_rt_put(rt); 412 ip_rt_put(rt);
412 icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu)); 413 icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
413 IP_VS_DBG_RL("%s(): frag needed\n", __func__); 414 IP_VS_DBG_RL("%s(): frag needed\n", __func__);
@@ -460,7 +461,7 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
460 461
461 /* MTU checking */ 462 /* MTU checking */
462 mtu = dst_mtu(&rt->dst); 463 mtu = dst_mtu(&rt->dst);
463 if (skb->len > mtu) { 464 if (skb->len > mtu && !skb_is_gso(skb)) {
464 if (!skb->dev) { 465 if (!skb->dev) {
465 struct net *net = dev_net(skb_dst(skb)->dev); 466 struct net *net = dev_net(skb_dst(skb)->dev);
466 467
@@ -560,7 +561,8 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
560 561
561 /* MTU checking */ 562 /* MTU checking */
562 mtu = dst_mtu(&rt->dst); 563 mtu = dst_mtu(&rt->dst);
563 if ((skb->len > mtu) && (iph->frag_off & htons(IP_DF))) { 564 if ((skb->len > mtu) && (iph->frag_off & htons(IP_DF)) &&
565 !skb_is_gso(skb)) {
564 icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu)); 566 icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
565 IP_VS_DBG_RL_PKT(0, AF_INET, pp, skb, 0, 567 IP_VS_DBG_RL_PKT(0, AF_INET, pp, skb, 0,
566 "ip_vs_nat_xmit(): frag needed for"); 568 "ip_vs_nat_xmit(): frag needed for");
@@ -675,7 +677,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
675 677
676 /* MTU checking */ 678 /* MTU checking */
677 mtu = dst_mtu(&rt->dst); 679 mtu = dst_mtu(&rt->dst);
678 if (skb->len > mtu) { 680 if (skb->len > mtu && !skb_is_gso(skb)) {
679 if (!skb->dev) { 681 if (!skb->dev) {
680 struct net *net = dev_net(skb_dst(skb)->dev); 682 struct net *net = dev_net(skb_dst(skb)->dev);
681 683
@@ -790,8 +792,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
790 792
791 df |= (old_iph->frag_off & htons(IP_DF)); 793 df |= (old_iph->frag_off & htons(IP_DF));
792 794
793 if ((old_iph->frag_off & htons(IP_DF)) 795 if ((old_iph->frag_off & htons(IP_DF) &&
794 && mtu < ntohs(old_iph->tot_len)) { 796 mtu < ntohs(old_iph->tot_len) && !skb_is_gso(skb))) {
795 icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu)); 797 icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
796 IP_VS_DBG_RL("%s(): frag needed\n", __func__); 798 IP_VS_DBG_RL("%s(): frag needed\n", __func__);
797 goto tx_error_put; 799 goto tx_error_put;
@@ -903,7 +905,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
903 if (skb_dst(skb)) 905 if (skb_dst(skb))
904 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); 906 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
905 907
906 if (mtu < ntohs(old_iph->payload_len) + sizeof(struct ipv6hdr)) { 908 if (mtu < ntohs(old_iph->payload_len) + sizeof(struct ipv6hdr) &&
909 !skb_is_gso(skb)) {
907 if (!skb->dev) { 910 if (!skb->dev) {
908 struct net *net = dev_net(skb_dst(skb)->dev); 911 struct net *net = dev_net(skb_dst(skb)->dev);
909 912
@@ -1008,7 +1011,8 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
1008 1011
1009 /* MTU checking */ 1012 /* MTU checking */
1010 mtu = dst_mtu(&rt->dst); 1013 mtu = dst_mtu(&rt->dst);
1011 if ((iph->frag_off & htons(IP_DF)) && skb->len > mtu) { 1014 if ((iph->frag_off & htons(IP_DF)) && skb->len > mtu &&
1015 !skb_is_gso(skb)) {
1012 icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu)); 1016 icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
1013 ip_rt_put(rt); 1017 ip_rt_put(rt);
1014 IP_VS_DBG_RL("%s(): frag needed\n", __func__); 1018 IP_VS_DBG_RL("%s(): frag needed\n", __func__);
@@ -1175,7 +1179,8 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
1175 1179
1176 /* MTU checking */ 1180 /* MTU checking */
1177 mtu = dst_mtu(&rt->dst); 1181 mtu = dst_mtu(&rt->dst);
1178 if ((skb->len > mtu) && (ip_hdr(skb)->frag_off & htons(IP_DF))) { 1182 if ((skb->len > mtu) && (ip_hdr(skb)->frag_off & htons(IP_DF)) &&
1183 !skb_is_gso(skb)) {
1179 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); 1184 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
1180 IP_VS_DBG_RL("%s(): frag needed\n", __func__); 1185 IP_VS_DBG_RL("%s(): frag needed\n", __func__);
1181 goto tx_error_put; 1186 goto tx_error_put;
@@ -1289,7 +1294,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
1289 1294
1290 /* MTU checking */ 1295 /* MTU checking */
1291 mtu = dst_mtu(&rt->dst); 1296 mtu = dst_mtu(&rt->dst);
1292 if (skb->len > mtu) { 1297 if (skb->len > mtu && !skb_is_gso(skb)) {
1293 if (!skb->dev) { 1298 if (!skb->dev) {
1294 struct net *net = dev_net(skb_dst(skb)->dev); 1299 struct net *net = dev_net(skb_dst(skb)->dev);
1295 1300