diff options
author | John Heffner <jheffner@psc.edu> | 2007-04-20 18:53:27 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:29:10 -0400 |
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 5a5b7d4ad31c..f508171bab73 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) | |||
137 | return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); | 137 | return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); |
138 | } | 138 | } |
139 | 139 | ||
140 | static inline int ip6_skb_dst_mtu(struct sk_buff *skb) | ||
141 | { | ||
142 | struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; | ||
143 | |||
144 | return (np && np->pmtudisc == IPV6_PMTUDISC_PROBE) ? | ||
145 | skb->dst->dev->mtu : dst_mtu(skb->dst); | ||
146 | } | ||
147 | |||
140 | int ip6_output(struct sk_buff *skb) | 148 | int ip6_output(struct sk_buff *skb) |
141 | { | 149 | { |
142 | if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) || | 150 | if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || |
143 | dst_allfrag(skb->dst)) | 151 | dst_allfrag(skb->dst)) |
144 | return ip6_fragment(skb, ip6_output2); | 152 | return ip6_fragment(skb, ip6_output2); |
145 | else | 153 | else |
@@ -566,7 +574,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
566 | hlen = ip6_find_1stfragopt(skb, &prevhdr); | 574 | hlen = ip6_find_1stfragopt(skb, &prevhdr); |
567 | nexthdr = *prevhdr; | 575 | nexthdr = *prevhdr; |
568 | 576 | ||
569 | mtu = dst_mtu(&rt->u.dst); | 577 | mtu = ip6_skb_dst_mtu(skb); |
570 | 578 | ||
571 | /* We must not fragment if the socket is set to force MTU discovery | 579 | /* We must not fragment if the socket is set to force MTU discovery |
572 | * or if the skb it not generated by a local socket. (This last | 580 | * 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, | |||
1063 | inet->cork.fl = *fl; | 1071 | inet->cork.fl = *fl; |
1064 | np->cork.hop_limit = hlimit; | 1072 | np->cork.hop_limit = hlimit; |
1065 | np->cork.tclass = tclass; | 1073 | np->cork.tclass = tclass; |
1066 | mtu = dst_mtu(rt->u.dst.path); | 1074 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? |
1075 | rt->u.dst.dev->mtu : dst_mtu(rt->u.dst.path); | ||
1067 | if (np->frag_size < mtu) { | 1076 | if (np->frag_size < mtu) { |
1068 | if (np->frag_size) | 1077 | if (np->frag_size) |
1069 | mtu = np->frag_size; | 1078 | mtu = np->frag_size; |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index da930fa089c9..aa3d07c52a8f 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -694,7 +694,7 @@ done: | |||
694 | retv = ip6_ra_control(sk, val, NULL); | 694 | retv = ip6_ra_control(sk, val, NULL); |
695 | break; | 695 | break; |
696 | case IPV6_MTU_DISCOVER: | 696 | case IPV6_MTU_DISCOVER: |
697 | if (val<0 || val>2) | 697 | if (val<0 || val>3) |
698 | goto e_inval; | 698 | goto e_inval; |
699 | np->pmtudisc = val; | 699 | np->pmtudisc = val; |
700 | retv = 0; | 700 | retv = 0; |