aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-07-17 13:48:26 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-17 13:48:26 -0400
commita6ff1a2f1e91578860b37df9fd861ef7af207de4 (patch)
tree1692579976add2fa59ab3fe008e4b0d36ec7ee30 /net/ipv6/route.c
parentbd2d0837abc0206ecdd3f6b9fc8c25b55b63c96b (diff)
parent4895c771c7f006b4b90f9d6b1d2210939ba57b38 (diff)
Merge branch 'nexthop_exceptions'
These patches implement the final mechanism necessary to really allow us to go without the route cache in ipv4. We need a place to have long-term storage of PMTU/redirect information which is independent of the routes themselves, yet does not get us back into a situation where we have to write to metrics or anything like that. For this we use an "next-hop exception" table in the FIB nexthops. The one thing I desperately want to avoid is having to create clone routes in the FIB trie for this purpose, because that is very expensive. However, I'm willing to entertain such an idea later if this current scheme proves to have downsides that the FIB trie variant would not have. In order to accomodate this any such scheme, we need to be able to produce a full flow key at PMTU/redirect time. That required an adjustment of the interface call-sites used to propagate these events. For a PMTU/redirect with a fully specified socket, we pass that socket and use it to produce the flow key. Otherwise we use a passed in SKB to formulate the key. There are two cases that need to be distinguished, ICMP message processing (in which case the IP header is at skb->data) and output packet processing (mostly tunnels, and in all such cases the IP header is at ip_hdr(skb)). We also have to make the code able to handle the case where the dst itself passed into the dst_ops->{update_pmtu,redirect} method is invalidated. This matters for calls from sockets that have cached that route. We provide a inet{,6} helper function for this purpose, and edit SCTP specially since it caches routes at the transport rather than socket level. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r--net/ipv6/route.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 412fad809a3b..84f6564dd372 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -78,8 +78,10 @@ static int ip6_dst_gc(struct dst_ops *ops);
78static int ip6_pkt_discard(struct sk_buff *skb); 78static int ip6_pkt_discard(struct sk_buff *skb);
79static int ip6_pkt_discard_out(struct sk_buff *skb); 79static int ip6_pkt_discard_out(struct sk_buff *skb);
80static void ip6_link_failure(struct sk_buff *skb); 80static void ip6_link_failure(struct sk_buff *skb);
81static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); 81static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
82static void rt6_do_redirect(struct dst_entry *dst, struct sk_buff *skb); 82 struct sk_buff *skb, u32 mtu);
83static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk,
84 struct sk_buff *skb);
83 85
84#ifdef CONFIG_IPV6_ROUTE_INFO 86#ifdef CONFIG_IPV6_ROUTE_INFO
85static struct rt6_info *rt6_add_route_info(struct net *net, 87static struct rt6_info *rt6_add_route_info(struct net *net,
@@ -187,11 +189,13 @@ static unsigned int ip6_blackhole_mtu(const struct dst_entry *dst)
187 return mtu ? : dst->dev->mtu; 189 return mtu ? : dst->dev->mtu;
188} 190}
189 191
190static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) 192static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk,
193 struct sk_buff *skb, u32 mtu)
191{ 194{
192} 195}
193 196
194static void ip6_rt_blackhole_redirect(struct dst_entry *dst, struct sk_buff *skb) 197static void ip6_rt_blackhole_redirect(struct dst_entry *dst, struct sock *sk,
198 struct sk_buff *skb)
195{ 199{
196} 200}
197 201
@@ -1071,7 +1075,8 @@ static void ip6_link_failure(struct sk_buff *skb)
1071 } 1075 }
1072} 1076}
1073 1077
1074static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) 1078static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
1079 struct sk_buff *skb, u32 mtu)
1075{ 1080{
1076 struct rt6_info *rt6 = (struct rt6_info*)dst; 1081 struct rt6_info *rt6 = (struct rt6_info*)dst;
1077 1082
@@ -1108,7 +1113,7 @@ void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
1108 1113
1109 dst = ip6_route_output(net, NULL, &fl6); 1114 dst = ip6_route_output(net, NULL, &fl6);
1110 if (!dst->error) 1115 if (!dst->error)
1111 ip6_rt_update_pmtu(dst, ntohl(mtu)); 1116 ip6_rt_update_pmtu(dst, NULL, skb, ntohl(mtu));
1112 dst_release(dst); 1117 dst_release(dst);
1113} 1118}
1114EXPORT_SYMBOL_GPL(ip6_update_pmtu); 1119EXPORT_SYMBOL_GPL(ip6_update_pmtu);
@@ -1136,7 +1141,7 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
1136 1141
1137 dst = ip6_route_output(net, NULL, &fl6); 1142 dst = ip6_route_output(net, NULL, &fl6);
1138 if (!dst->error) 1143 if (!dst->error)
1139 rt6_do_redirect(dst, skb); 1144 rt6_do_redirect(dst, NULL, skb);
1140 dst_release(dst); 1145 dst_release(dst);
1141} 1146}
1142EXPORT_SYMBOL_GPL(ip6_redirect); 1147EXPORT_SYMBOL_GPL(ip6_redirect);
@@ -1639,7 +1644,7 @@ static int ip6_route_del(struct fib6_config *cfg)
1639 return err; 1644 return err;
1640} 1645}
1641 1646
1642static void rt6_do_redirect(struct dst_entry *dst, struct sk_buff *skb) 1647static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb)
1643{ 1648{
1644 struct net *net = dev_net(skb->dev); 1649 struct net *net = dev_net(skb->dev);
1645 struct netevent_redirect netevent; 1650 struct netevent_redirect netevent;