diff options
author | John Heffner <jheffner@psc.edu> | 2007-04-20 15:53:27 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-25 22:29:10 -0700 |
commit | 628a5c561890a9a9a74dea017873530584aab06e (patch) | |
tree | f10edc4078c3f19487bbe3a902ecadda89273361 /net/ipv6 | |
parent | b881ef7603230550aa0150b22af94089f07ab00d (diff) |
[INET]: Add IP(V6)_PMTUDISC_RPOBE
Add IP(V6)_PMTUDISC_PROBE value for IP(V6)_MTU_DISCOVER. This option forces
us not to fragment, but does not make use of the kernel path MTU discovery.
That is, it allows for user-mode MTU probing (or, packetization-layer path
MTU discovery). This is particularly useful for diagnostic utilities, like
traceroute/tracepath.
Signed-off-by: John Heffner <jheffner@psc.edu>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/ip6_output.c | 15 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 2 |
2 files changed, 13 insertions, 4 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 5a5b7d4ad31..f508171bab7 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -137,9 +137,17 @@ static int ip6_output2(struct sk_buff *skb) return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); } +static inline int ip6_skb_dst_mtu(struct sk_buff *skb) +{ + struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; + + return (np && np->pmtudisc == IPV6_PMTUDISC_PROBE) ? + skb->dst->dev->mtu : dst_mtu(skb->dst); +} + int ip6_output(struct sk_buff *skb) { - if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) || + if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || dst_allfrag(skb->dst)) return ip6_fragment(skb, ip6_output2); else @@ -566,7 +574,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) hlen = ip6_find_1stfragopt(skb, &prevhdr); nexthdr = *prevhdr; - mtu = dst_mtu(&rt->u.dst); + mtu = ip6_skb_dst_mtu(skb); /* We must not fragment if the socket is set to force MTU discovery * or if the skb it not generated by a local socket. (This last @@ -1063,7 +1071,8 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, inet->cork.fl = *fl; np->cork.hop_limit = hlimit; np->cork.tclass = tclass; - mtu = dst_mtu(rt->u.dst.path); + mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? + rt->u.dst.dev->mtu : dst_mtu(rt->u.dst.path); if (np->frag_size < mtu) { if (np->frag_size) mtu = np->frag_size; diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index da930fa089c..aa3d07c52a8 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -694,7 +694,7 @@ done: retv = ip6_ra_control(sk, val, NULL); break; case IPV6_MTU_DISCOVER: - if (val<0 || val>2) + if (val<0 || val>3) goto e_inval; np->pmtudisc = val; retv = 0; |