diff options
author | wenxu <wenxu@ucloud.cn> | 2019-01-22 05:39:50 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-01-26 12:43:03 -0500 |
commit | c8b34e680a090ab8dc42f8331020e31052b49a70 (patch) | |
tree | 5db6a530d23ffb492611e47f35c112f81ef14c49 | |
parent | f46fe4f8d787bd66005120460317939b8c6d7c70 (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.h | 2 | ||||
-rw-r--r-- | net/ipv4/ip_tunnel.c | 37 | ||||
-rw-r--r-- | net/ipv4/ipip.c | 2 |
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, | |||
267 | void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | 267 | void 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); |
269 | void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | 269 | void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, |
270 | const u8 proto); | 270 | const u8 proto, int tunnel_hlen); |
271 | int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd); | 271 | int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd); |
272 | int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict); | 272 | int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict); |
273 | int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu); | 273 | int 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 | ||
502 | static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, | 502 | static 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 | ||
551 | void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, u8 proto) | 557 | void 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; |