summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwenxu <wenxu@ucloud.cn>2019-01-22 05:39:50 -0500
committerDavid S. Miller <davem@davemloft.net>2019-01-26 12:43:03 -0500
commitc8b34e680a090ab8dc42f8331020e31052b49a70 (patch)
tree5db6a530d23ffb492611e47f35c112f81ef14c49
parentf46fe4f8d787bd66005120460317939b8c6d7c70 (diff)
ip_tunnel: Add tnl_update_pmtu in ip_md_tunnel_xmit
Add tnl_update_pmtu in ip_md_tunnel_xmit to dynamic modify the pmtu which packet send through collect_metadata mode ip tunnel Signed-off-by: wenxu <wenxu@ucloud.cn> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/ip_tunnels.h2
-rw-r--r--net/ipv4/ip_tunnel.c37
-rw-r--r--net/ipv4/ipip.c2
3 files changed, 29 insertions, 12 deletions
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 34f019650941..f069f64ebf29 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -267,7 +267,7 @@ void ip_tunnel_delete_nets(struct list_head *list_net, unsigned int id,
267void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, 267void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
268 const struct iphdr *tnl_params, const u8 protocol); 268 const struct iphdr *tnl_params, const u8 protocol);
269void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, 269void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
270 const u8 proto); 270 const u8 proto, int tunnel_hlen);
271int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd); 271int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd);
272int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict); 272int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict);
273int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu); 273int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu);
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index f98fc4c983a5..6233a7c434b1 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -501,15 +501,19 @@ EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup);
501 501
502static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, 502static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
503 struct rtable *rt, __be16 df, 503 struct rtable *rt, __be16 df,
504 const struct iphdr *inner_iph) 504 const struct iphdr *inner_iph,
505 int tunnel_hlen, __be32 dst, bool md)
505{ 506{
506 struct ip_tunnel *tunnel = netdev_priv(dev); 507 struct ip_tunnel *tunnel = netdev_priv(dev);
507 int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len; 508 int pkt_size;
508 int mtu; 509 int mtu;
509 510
511 tunnel_hlen = md ? tunnel_hlen : tunnel->hlen;
512 pkt_size = skb->len - tunnel_hlen - dev->hard_header_len;
513
510 if (df) 514 if (df)
511 mtu = dst_mtu(&rt->dst) - dev->hard_header_len 515 mtu = dst_mtu(&rt->dst) - dev->hard_header_len
512 - sizeof(struct iphdr) - tunnel->hlen; 516 - sizeof(struct iphdr) - tunnel_hlen;
513 else 517 else
514 mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; 518 mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
515 519
@@ -527,11 +531,13 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
527#if IS_ENABLED(CONFIG_IPV6) 531#if IS_ENABLED(CONFIG_IPV6)
528 else if (skb->protocol == htons(ETH_P_IPV6)) { 532 else if (skb->protocol == htons(ETH_P_IPV6)) {
529 struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb); 533 struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
534 __be32 daddr;
535
536 daddr = md ? dst : tunnel->parms.iph.daddr;
530 537
531 if (rt6 && mtu < dst_mtu(skb_dst(skb)) && 538 if (rt6 && mtu < dst_mtu(skb_dst(skb)) &&
532 mtu >= IPV6_MIN_MTU) { 539 mtu >= IPV6_MIN_MTU) {
533 if ((tunnel->parms.iph.daddr && 540 if ((daddr && !ipv4_is_multicast(daddr)) ||
534 !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
535 rt6->rt6i_dst.plen == 128) { 541 rt6->rt6i_dst.plen == 128) {
536 rt6->rt6i_flags |= RTF_MODIFIED; 542 rt6->rt6i_flags |= RTF_MODIFIED;
537 dst_metric_set(skb_dst(skb), RTAX_MTU, mtu); 543 dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
@@ -548,7 +554,8 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
548 return 0; 554 return 0;
549} 555}
550 556
551void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, u8 proto) 557void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
558 u8 proto, int tunnel_hlen)
552{ 559{
553 struct ip_tunnel *tunnel = netdev_priv(dev); 560 struct ip_tunnel *tunnel = netdev_priv(dev);
554 u32 headroom = sizeof(struct iphdr); 561 u32 headroom = sizeof(struct iphdr);
@@ -598,6 +605,15 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, u8 proto)
598 dev->stats.collisions++; 605 dev->stats.collisions++;
599 goto tx_error; 606 goto tx_error;
600 } 607 }
608
609 if (key->tun_flags & TUNNEL_DONT_FRAGMENT)
610 df = htons(IP_DF);
611 if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, tunnel_hlen,
612 key->u.ipv4.dst, true)) {
613 ip_rt_put(rt);
614 goto tx_error;
615 }
616
601 tos = ip_tunnel_ecn_encap(tos, inner_iph, skb); 617 tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
602 ttl = key->ttl; 618 ttl = key->ttl;
603 if (ttl == 0) { 619 if (ttl == 0) {
@@ -608,10 +624,10 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, u8 proto)
608 else 624 else
609 ttl = ip4_dst_hoplimit(&rt->dst); 625 ttl = ip4_dst_hoplimit(&rt->dst);
610 } 626 }
611 if (key->tun_flags & TUNNEL_DONT_FRAGMENT) 627
612 df = htons(IP_DF); 628 if (!df && skb->protocol == htons(ETH_P_IP))
613 else if (skb->protocol == htons(ETH_P_IP))
614 df = inner_iph->frag_off & htons(IP_DF); 629 df = inner_iph->frag_off & htons(IP_DF);
630
615 headroom += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len; 631 headroom += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len;
616 if (headroom > dev->needed_headroom) 632 if (headroom > dev->needed_headroom)
617 dev->needed_headroom = headroom; 633 dev->needed_headroom = headroom;
@@ -741,7 +757,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
741 goto tx_error; 757 goto tx_error;
742 } 758 }
743 759
744 if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off, inner_iph)) { 760 if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off, inner_iph,
761 0, 0, false)) {
745 ip_rt_put(rt); 762 ip_rt_put(rt);
746 goto tx_error; 763 goto tx_error;
747 } 764 }
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 57c5dd283a2c..fe10b9a2efc8 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -302,7 +302,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb,
302 skb_set_inner_ipproto(skb, ipproto); 302 skb_set_inner_ipproto(skb, ipproto);
303 303
304 if (tunnel->collect_md) 304 if (tunnel->collect_md)
305 ip_md_tunnel_xmit(skb, dev, ipproto); 305 ip_md_tunnel_xmit(skb, dev, ipproto, 0);
306 else 306 else
307 ip_tunnel_xmit(skb, dev, tiph, ipproto); 307 ip_tunnel_xmit(skb, dev, tiph, ipproto);
308 return NETDEV_TX_OK; 308 return NETDEV_TX_OK;