aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorJohn Heffner <jheffner@psc.edu>2007-04-20 18:53:27 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:29:10 -0400
commit628a5c561890a9a9a74dea017873530584aab06e (patch)
treef10edc4078c3f19487bbe3a902ecadda89273361 /net/ipv6
parentb881ef7603230550aa0150b22af94089f07ab00d (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.c15
-rw-r--r--net/ipv6/ipv6_sockglue.c2
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
140static 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
140int ip6_output(struct sk_buff *skb) 148int 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;