diff options
author | Steffen Klassert <steffen.klassert@secunet.com> | 2014-03-14 02:28:08 -0400 |
---|---|---|
committer | Steffen Klassert <steffen.klassert@secunet.com> | 2014-03-14 02:28:08 -0400 |
commit | 7c85258152d639868091c8c4bb6b5364c108f074 (patch) | |
tree | 45dcd2b8c8e0e579934a30508ce9667a7923bb54 /net/ipv6 | |
parent | 59b84351c0ee97501782988af5ec9c004c4d30ac (diff) |
vti6: Remove dst_entry caching
Unlike ip6_tunnel, vti6 can lookup multiple different dst entries,
dependent of the configured xfrm states. Therefore it does not make
sense to cache a dst_entry.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/ip6_vti.c | 42 |
1 files changed, 18 insertions, 24 deletions
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 864914399391..f5ba4d42b4ae 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c | |||
@@ -278,7 +278,6 @@ static void vti6_dev_uninit(struct net_device *dev) | |||
278 | RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL); | 278 | RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL); |
279 | else | 279 | else |
280 | vti6_tnl_unlink(ip6n, t); | 280 | vti6_tnl_unlink(ip6n, t); |
281 | ip6_tnl_dst_reset(t); | ||
282 | dev_put(dev); | 281 | dev_put(dev); |
283 | } | 282 | } |
284 | 283 | ||
@@ -356,11 +355,10 @@ vti6_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr) | |||
356 | **/ | 355 | **/ |
357 | static int vti6_xmit(struct sk_buff *skb, struct net_device *dev) | 356 | static int vti6_xmit(struct sk_buff *skb, struct net_device *dev) |
358 | { | 357 | { |
359 | struct net *net = dev_net(dev); | ||
360 | struct ip6_tnl *t = netdev_priv(dev); | 358 | struct ip6_tnl *t = netdev_priv(dev); |
361 | struct net_device_stats *stats = &t->dev->stats; | 359 | struct net_device_stats *stats = &t->dev->stats; |
362 | struct dst_entry *dst = NULL, *ndst = NULL; | 360 | struct dst_entry *dst = skb_dst(skb); |
363 | struct flowi6 fl6; | 361 | struct flowi fl; |
364 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 362 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
365 | struct net_device *tdev; | 363 | struct net_device *tdev; |
366 | int err = -1; | 364 | int err = -1; |
@@ -369,21 +367,19 @@ static int vti6_xmit(struct sk_buff *skb, struct net_device *dev) | |||
369 | !ip6_tnl_xmit_ctl(t) || vti6_addr_conflict(t, ipv6h)) | 367 | !ip6_tnl_xmit_ctl(t) || vti6_addr_conflict(t, ipv6h)) |
370 | return err; | 368 | return err; |
371 | 369 | ||
372 | dst = ip6_tnl_dst_check(t); | 370 | memset(&fl, 0, sizeof(fl)); |
373 | if (!dst) { | 371 | skb->mark = be32_to_cpu(t->parms.o_key); |
374 | memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); | 372 | xfrm_decode_session(skb, &fl, AF_INET6); |
375 | 373 | ||
376 | ndst = ip6_route_output(net, NULL, &fl6); | 374 | if (!dst) |
375 | goto tx_err_link_failure; | ||
377 | 376 | ||
378 | if (ndst->error) | 377 | dst_hold(dst); |
379 | goto tx_err_link_failure; | 378 | dst = xfrm_lookup(t->net, dst, &fl, NULL, 0); |
380 | ndst = xfrm_lookup(net, ndst, flowi6_to_flowi(&fl6), NULL, 0); | 379 | if (IS_ERR(dst)) { |
381 | if (IS_ERR(ndst)) { | 380 | err = PTR_ERR(dst); |
382 | err = PTR_ERR(ndst); | 381 | dst = NULL; |
383 | ndst = NULL; | 382 | goto tx_err_link_failure; |
384 | goto tx_err_link_failure; | ||
385 | } | ||
386 | dst = ndst; | ||
387 | } | 383 | } |
388 | 384 | ||
389 | if (!dst->xfrm || dst->xfrm->props.mode != XFRM_MODE_TUNNEL) | 385 | if (!dst->xfrm || dst->xfrm->props.mode != XFRM_MODE_TUNNEL) |
@@ -399,21 +395,19 @@ static int vti6_xmit(struct sk_buff *skb, struct net_device *dev) | |||
399 | } | 395 | } |
400 | 396 | ||
401 | 397 | ||
402 | skb_dst_drop(skb); | 398 | memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); |
403 | skb_dst_set_noref(skb, dst); | 399 | skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev))); |
400 | skb_dst_set(skb, dst); | ||
401 | skb->dev = skb_dst(skb)->dev; | ||
404 | 402 | ||
405 | ip6tunnel_xmit(skb, dev); | 403 | ip6tunnel_xmit(skb, dev); |
406 | if (ndst) { | ||
407 | dev->mtu = dst_mtu(ndst); | ||
408 | ip6_tnl_dst_store(t, ndst); | ||
409 | } | ||
410 | 404 | ||
411 | return 0; | 405 | return 0; |
412 | tx_err_link_failure: | 406 | tx_err_link_failure: |
413 | stats->tx_carrier_errors++; | 407 | stats->tx_carrier_errors++; |
414 | dst_link_failure(skb); | 408 | dst_link_failure(skb); |
415 | tx_err_dst_release: | 409 | tx_err_dst_release: |
416 | dst_release(ndst); | 410 | dst_release(dst); |
417 | return err; | 411 | return err; |
418 | } | 412 | } |
419 | 413 | ||