route.c (ddb9e13af3bba3f8c36ccee0eb9563a82b425c12) route.c (31afeb425f7fad8bcf9561aeb0b8405479f97a98)
1/*
2 * Linux INET6 implementation
3 * FIB front-end.
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * This program is free software; you can redistribute it and/or

--- 172 unchanged lines hidden (view full) ---

181 }
182 }
183 spin_unlock_bh(&ul->lock);
184 }
185}
186
187static u32 *rt6_pcpu_cow_metrics(struct rt6_info *rt)
188{
1/*
2 * Linux INET6 implementation
3 * FIB front-end.
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * This program is free software; you can redistribute it and/or

--- 172 unchanged lines hidden (view full) ---

181 }
182 }
183 spin_unlock_bh(&ul->lock);
184 }
185}
186
187static u32 *rt6_pcpu_cow_metrics(struct rt6_info *rt)
188{
189 return dst_metrics_write_ptr(rt->dst.from);
189 return dst_metrics_write_ptr(&rt->from->dst);
190}
191
192static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
193{
194 struct rt6_info *rt = (struct rt6_info *)dst;
195
196 if (rt->rt6i_flags & RTF_PCPU)
197 return rt6_pcpu_cow_metrics(rt);

--- 188 unchanged lines hidden (view full) ---

386 return rt;
387}
388EXPORT_SYMBOL(ip6_dst_alloc);
389
390static void ip6_dst_destroy(struct dst_entry *dst)
391{
392 struct rt6_info *rt = (struct rt6_info *)dst;
393 struct rt6_exception_bucket *bucket;
190}
191
192static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
193{
194 struct rt6_info *rt = (struct rt6_info *)dst;
195
196 if (rt->rt6i_flags & RTF_PCPU)
197 return rt6_pcpu_cow_metrics(rt);

--- 188 unchanged lines hidden (view full) ---

386 return rt;
387}
388EXPORT_SYMBOL(ip6_dst_alloc);
389
390static void ip6_dst_destroy(struct dst_entry *dst)
391{
392 struct rt6_info *rt = (struct rt6_info *)dst;
393 struct rt6_exception_bucket *bucket;
394 struct dst_entry *from = dst->from;
394 struct rt6_info *from = rt->from;
395 struct inet6_dev *idev;
396
397 dst_destroy_metrics_generic(dst);
398 free_percpu(rt->rt6i_pcpu);
399 rt6_uncached_list_del(rt);
400
401 idev = rt->rt6i_idev;
402 if (idev) {
403 rt->rt6i_idev = NULL;
404 in6_dev_put(idev);
405 }
406 bucket = rcu_dereference_protected(rt->rt6i_exception_bucket, 1);
407 if (bucket) {
408 rt->rt6i_exception_bucket = NULL;
409 kfree(bucket);
410 }
411
395 struct inet6_dev *idev;
396
397 dst_destroy_metrics_generic(dst);
398 free_percpu(rt->rt6i_pcpu);
399 rt6_uncached_list_del(rt);
400
401 idev = rt->rt6i_idev;
402 if (idev) {
403 rt->rt6i_idev = NULL;
404 in6_dev_put(idev);
405 }
406 bucket = rcu_dereference_protected(rt->rt6i_exception_bucket, 1);
407 if (bucket) {
408 rt->rt6i_exception_bucket = NULL;
409 kfree(bucket);
410 }
411
412 dst->from = NULL;
413 dst_release(from);
412 rt->from = NULL;
413 dst_release(&from->dst);
414}
415
416static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
417 int how)
418{
419 struct rt6_info *rt = (struct rt6_info *)dst;
420 struct inet6_dev *idev = rt->rt6i_idev;
421 struct net_device *loopback_dev =

--- 16 unchanged lines hidden (view full) ---

438 return false;
439}
440
441static bool rt6_check_expired(const struct rt6_info *rt)
442{
443 if (rt->rt6i_flags & RTF_EXPIRES) {
444 if (time_after(jiffies, rt->dst.expires))
445 return true;
414}
415
416static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
417 int how)
418{
419 struct rt6_info *rt = (struct rt6_info *)dst;
420 struct inet6_dev *idev = rt->rt6i_idev;
421 struct net_device *loopback_dev =

--- 16 unchanged lines hidden (view full) ---

438 return false;
439}
440
441static bool rt6_check_expired(const struct rt6_info *rt)
442{
443 if (rt->rt6i_flags & RTF_EXPIRES) {
444 if (time_after(jiffies, rt->dst.expires))
445 return true;
446 } else if (rt->dst.from) {
446 } else if (rt->from) {
447 return rt->dst.obsolete != DST_OBSOLETE_FORCE_CHK ||
447 return rt->dst.obsolete != DST_OBSOLETE_FORCE_CHK ||
448 rt6_check_expired((struct rt6_info *)rt->dst.from);
448 rt6_check_expired(rt->from);
449 }
450 return false;
451}
452
453static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
454 struct flowi6 *fl6, int oif,
455 int strict)
456{
457 struct rt6_info *sibling, *next_sibling;
449 }
450 return false;
451}
452
453static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
454 struct flowi6 *fl6, int oif,
455 int strict)
456{
457 struct rt6_info *sibling, *next_sibling;
458 int route_choosen;
459
460 /* We might have already computed the hash for ICMPv6 errors. In such
461 * case it will always be non-zero. Otherwise now is the time to do it.
462 */
463 if (!fl6->mp_hash)
464 fl6->mp_hash = rt6_multipath_hash(fl6, NULL);
465
458
459 /* We might have already computed the hash for ICMPv6 errors. In such
460 * case it will always be non-zero. Otherwise now is the time to do it.
461 */
462 if (!fl6->mp_hash)
463 fl6->mp_hash = rt6_multipath_hash(fl6, NULL);
464
466 route_choosen = fl6->mp_hash % (match->rt6i_nsiblings + 1);
467 /* Don't change the route, if route_choosen == 0
468 * (siblings does not include ourself)
469 */
470 if (route_choosen)
471 list_for_each_entry_safe(sibling, next_sibling,
472 &match->rt6i_siblings, rt6i_siblings) {
473 route_choosen--;
474 if (route_choosen == 0) {
475 struct inet6_dev *idev = sibling->rt6i_idev;
465 if (fl6->mp_hash <= atomic_read(&match->rt6i_nh_upper_bound))
466 return match;
476
467
477 if (!netif_carrier_ok(sibling->dst.dev) &&
478 idev->cnf.ignore_routes_with_linkdown)
479 break;
480 if (rt6_score_route(sibling, oif, strict) < 0)
481 break;
482 match = sibling;
483 break;
484 }
485 }
468 list_for_each_entry_safe(sibling, next_sibling, &match->rt6i_siblings,
469 rt6i_siblings) {
470 if (fl6->mp_hash > atomic_read(&sibling->rt6i_nh_upper_bound))
471 continue;
472 if (rt6_score_route(sibling, oif, strict) < 0)
473 break;
474 match = sibling;
475 break;
476 }
477
486 return match;
487}
488
489/*
490 * Route lookup. rcu_read_lock() should be held.
491 */
492
493static inline struct rt6_info *rt6_device_match(struct net *net,
494 struct rt6_info *rt,
495 const struct in6_addr *saddr,
496 int oif,
497 int flags)
498{
499 struct rt6_info *local = NULL;
500 struct rt6_info *sprt;
501
478 return match;
479}
480
481/*
482 * Route lookup. rcu_read_lock() should be held.
483 */
484
485static inline struct rt6_info *rt6_device_match(struct net *net,
486 struct rt6_info *rt,
487 const struct in6_addr *saddr,
488 int oif,
489 int flags)
490{
491 struct rt6_info *local = NULL;
492 struct rt6_info *sprt;
493
502 if (!oif && ipv6_addr_any(saddr))
503 goto out;
494 if (!oif && ipv6_addr_any(saddr) && !(rt->rt6i_nh_flags & RTNH_F_DEAD))
495 return rt;
504
496
505 for (sprt = rt; sprt; sprt = rcu_dereference(sprt->dst.rt6_next)) {
497 for (sprt = rt; sprt; sprt = rcu_dereference(sprt->rt6_next)) {
506 struct net_device *dev = sprt->dst.dev;
507
498 struct net_device *dev = sprt->dst.dev;
499
500 if (sprt->rt6i_nh_flags & RTNH_F_DEAD)
501 continue;
502
508 if (oif) {
509 if (dev->ifindex == oif)
510 return sprt;
511 if (dev->flags & IFF_LOOPBACK) {
512 if (!sprt->rt6i_idev ||
513 sprt->rt6i_idev->dev->ifindex != oif) {
514 if (flags & RT6_LOOKUP_F_IFACE)
515 continue;

--- 12 unchanged lines hidden (view full) ---

528
529 if (oif) {
530 if (local)
531 return local;
532
533 if (flags & RT6_LOOKUP_F_IFACE)
534 return net->ipv6.ip6_null_entry;
535 }
503 if (oif) {
504 if (dev->ifindex == oif)
505 return sprt;
506 if (dev->flags & IFF_LOOPBACK) {
507 if (!sprt->rt6i_idev ||
508 sprt->rt6i_idev->dev->ifindex != oif) {
509 if (flags & RT6_LOOKUP_F_IFACE)
510 continue;

--- 12 unchanged lines hidden (view full) ---

523
524 if (oif) {
525 if (local)
526 return local;
527
528 if (flags & RT6_LOOKUP_F_IFACE)
529 return net->ipv6.ip6_null_entry;
530 }
536out:
537 return rt;
531
532 return rt->rt6i_nh_flags & RTNH_F_DEAD ? net->ipv6.ip6_null_entry : rt;
538}
539
540#ifdef CONFIG_IPV6_ROUTER_PREF
541struct __rt6_probe_work {
542 struct work_struct work;
543 struct in6_addr target;
544 struct net_device *dev;
545};

--- 128 unchanged lines hidden (view full) ---

674
675static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
676 int *mpri, struct rt6_info *match,
677 bool *do_rr)
678{
679 int m;
680 bool match_do_rr = false;
681 struct inet6_dev *idev = rt->rt6i_idev;
533}
534
535#ifdef CONFIG_IPV6_ROUTER_PREF
536struct __rt6_probe_work {
537 struct work_struct work;
538 struct in6_addr target;
539 struct net_device *dev;
540};

--- 128 unchanged lines hidden (view full) ---

669
670static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
671 int *mpri, struct rt6_info *match,
672 bool *do_rr)
673{
674 int m;
675 bool match_do_rr = false;
676 struct inet6_dev *idev = rt->rt6i_idev;
682 struct net_device *dev = rt->dst.dev;
683
677
684 if (dev && !netif_carrier_ok(dev) &&
685 idev->cnf.ignore_routes_with_linkdown &&
678 if (rt->rt6i_nh_flags & RTNH_F_DEAD)
679 goto out;
680
681 if (idev->cnf.ignore_routes_with_linkdown &&
682 rt->rt6i_nh_flags & RTNH_F_LINKDOWN &&
686 !(strict & RT6_LOOKUP_F_IGNORE_LINKSTATE))
687 goto out;
688
689 if (rt6_check_expired(rt))
690 goto out;
691
692 m = rt6_score_route(rt, oif, strict);
693 if (m == RT6_NUD_FAIL_DO_RR) {

--- 22 unchanged lines hidden (view full) ---

716 u32 metric, int oif, int strict,
717 bool *do_rr)
718{
719 struct rt6_info *rt, *match, *cont;
720 int mpri = -1;
721
722 match = NULL;
723 cont = NULL;
683 !(strict & RT6_LOOKUP_F_IGNORE_LINKSTATE))
684 goto out;
685
686 if (rt6_check_expired(rt))
687 goto out;
688
689 m = rt6_score_route(rt, oif, strict);
690 if (m == RT6_NUD_FAIL_DO_RR) {

--- 22 unchanged lines hidden (view full) ---

713 u32 metric, int oif, int strict,
714 bool *do_rr)
715{
716 struct rt6_info *rt, *match, *cont;
717 int mpri = -1;
718
719 match = NULL;
720 cont = NULL;
724 for (rt = rr_head; rt; rt = rcu_dereference(rt->dst.rt6_next)) {
721 for (rt = rr_head; rt; rt = rcu_dereference(rt->rt6_next)) {
725 if (rt->rt6i_metric != metric) {
726 cont = rt;
727 break;
728 }
729
730 match = find_match(rt, oif, strict, &mpri, match, do_rr);
731 }
732
733 for (rt = leaf; rt && rt != rr_head;
722 if (rt->rt6i_metric != metric) {
723 cont = rt;
724 break;
725 }
726
727 match = find_match(rt, oif, strict, &mpri, match, do_rr);
728 }
729
730 for (rt = leaf; rt && rt != rr_head;
734 rt = rcu_dereference(rt->dst.rt6_next)) {
731 rt = rcu_dereference(rt->rt6_next)) {
735 if (rt->rt6i_metric != metric) {
736 cont = rt;
737 break;
738 }
739
740 match = find_match(rt, oif, strict, &mpri, match, do_rr);
741 }
742
743 if (match || !cont)
744 return match;
745
732 if (rt->rt6i_metric != metric) {
733 cont = rt;
734 break;
735 }
736
737 match = find_match(rt, oif, strict, &mpri, match, do_rr);
738 }
739
740 if (match || !cont)
741 return match;
742
746 for (rt = cont; rt; rt = rcu_dereference(rt->dst.rt6_next))
743 for (rt = cont; rt; rt = rcu_dereference(rt->rt6_next))
747 match = find_match(rt, oif, strict, &mpri, match, do_rr);
748
749 return match;
750}
751
752static struct rt6_info *rt6_select(struct net *net, struct fib6_node *fn,
753 int oif, int strict)
754{

--- 21 unchanged lines hidden (view full) ---

776#endif
777 if (fn->fn_bit != key_plen)
778 return net->ipv6.ip6_null_entry;
779
780 match = find_rr_leaf(fn, leaf, rt0, rt0->rt6i_metric, oif, strict,
781 &do_rr);
782
783 if (do_rr) {
744 match = find_match(rt, oif, strict, &mpri, match, do_rr);
745
746 return match;
747}
748
749static struct rt6_info *rt6_select(struct net *net, struct fib6_node *fn,
750 int oif, int strict)
751{

--- 21 unchanged lines hidden (view full) ---

773#endif
774 if (fn->fn_bit != key_plen)
775 return net->ipv6.ip6_null_entry;
776
777 match = find_rr_leaf(fn, leaf, rt0, rt0->rt6i_metric, oif, strict,
778 &do_rr);
779
780 if (do_rr) {
784 struct rt6_info *next = rcu_dereference(rt0->dst.rt6_next);
781 struct rt6_info *next = rcu_dereference(rt0->rt6_next);
785
786 /* no entries matched; do round-robin */
787 if (!next || next->rt6i_metric != rt0->rt6i_metric)
788 next = leaf;
789
790 if (next != rt0) {
791 spin_lock_bh(&leaf->rt6i_table->tb6_lock);
792 /* make sure next is not being deleted from the tree */

--- 256 unchanged lines hidden (view full) ---

1049 struct net_device *dev;
1050 struct rt6_info *rt;
1051
1052 /*
1053 * Clone the route.
1054 */
1055
1056 if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
782
783 /* no entries matched; do round-robin */
784 if (!next || next->rt6i_metric != rt0->rt6i_metric)
785 next = leaf;
786
787 if (next != rt0) {
788 spin_lock_bh(&leaf->rt6i_table->tb6_lock);
789 /* make sure next is not being deleted from the tree */

--- 256 unchanged lines hidden (view full) ---

1046 struct net_device *dev;
1047 struct rt6_info *rt;
1048
1049 /*
1050 * Clone the route.
1051 */
1052
1053 if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
1057 ort = (struct rt6_info *)ort->dst.from;
1054 ort = ort->from;
1058
1059 rcu_read_lock();
1060 dev = ip6_rt_get_dev_rcu(ort);
1061 rt = __ip6_dst_alloc(dev_net(dev), dev, 0);
1062 rcu_read_unlock();
1063 if (!rt)
1064 return NULL;
1065

--- 203 unchanged lines hidden (view full) ---

1269 struct net *net = dev_net(ort->dst.dev);
1270 struct rt6_exception_bucket *bucket;
1271 struct in6_addr *src_key = NULL;
1272 struct rt6_exception *rt6_ex;
1273 int err = 0;
1274
1275 /* ort can't be a cache or pcpu route */
1276 if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
1055
1056 rcu_read_lock();
1057 dev = ip6_rt_get_dev_rcu(ort);
1058 rt = __ip6_dst_alloc(dev_net(dev), dev, 0);
1059 rcu_read_unlock();
1060 if (!rt)
1061 return NULL;
1062

--- 203 unchanged lines hidden (view full) ---

1266 struct net *net = dev_net(ort->dst.dev);
1267 struct rt6_exception_bucket *bucket;
1268 struct in6_addr *src_key = NULL;
1269 struct rt6_exception *rt6_ex;
1270 int err = 0;
1271
1272 /* ort can't be a cache or pcpu route */
1273 if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
1277 ort = (struct rt6_info *)ort->dst.from;
1274 ort = ort->from;
1278 WARN_ON_ONCE(ort->rt6i_flags & (RTF_CACHE | RTF_PCPU));
1279
1280 spin_lock_bh(&rt6_exception_lock);
1281
1282 if (ort->exception_bucket_flushed) {
1283 err = -EINVAL;
1284 goto out;
1285 }

--- 55 unchanged lines hidden (view full) ---

1341 if (bucket->depth > FIB6_MAX_DEPTH)
1342 rt6_exception_remove_oldest(bucket);
1343
1344out:
1345 spin_unlock_bh(&rt6_exception_lock);
1346
1347 /* Update fn->fn_sernum to invalidate all cached dst */
1348 if (!err) {
1275 WARN_ON_ONCE(ort->rt6i_flags & (RTF_CACHE | RTF_PCPU));
1276
1277 spin_lock_bh(&rt6_exception_lock);
1278
1279 if (ort->exception_bucket_flushed) {
1280 err = -EINVAL;
1281 goto out;
1282 }

--- 55 unchanged lines hidden (view full) ---

1338 if (bucket->depth > FIB6_MAX_DEPTH)
1339 rt6_exception_remove_oldest(bucket);
1340
1341out:
1342 spin_unlock_bh(&rt6_exception_lock);
1343
1344 /* Update fn->fn_sernum to invalidate all cached dst */
1345 if (!err) {
1346 spin_lock_bh(&ort->rt6i_table->tb6_lock);
1349 fib6_update_sernum(ort);
1347 fib6_update_sernum(ort);
1348 spin_unlock_bh(&ort->rt6i_table->tb6_lock);
1350 fib6_force_start_gc(net);
1351 }
1352
1353 return err;
1354}
1355
1356void rt6_flush_exceptions(struct rt6_info *rt)
1357{

--- 52 unchanged lines hidden (view full) ---

1410 res = rt6_ex->rt6i;
1411
1412 return res;
1413}
1414
1415/* Remove the passed in cached rt from the hash table that contains it */
1416int rt6_remove_exception_rt(struct rt6_info *rt)
1417{
1349 fib6_force_start_gc(net);
1350 }
1351
1352 return err;
1353}
1354
1355void rt6_flush_exceptions(struct rt6_info *rt)
1356{

--- 52 unchanged lines hidden (view full) ---

1409 res = rt6_ex->rt6i;
1410
1411 return res;
1412}
1413
1414/* Remove the passed in cached rt from the hash table that contains it */
1415int rt6_remove_exception_rt(struct rt6_info *rt)
1416{
1418 struct rt6_info *from = (struct rt6_info *)rt->dst.from;
1419 struct rt6_exception_bucket *bucket;
1417 struct rt6_exception_bucket *bucket;
1418 struct rt6_info *from = rt->from;
1420 struct in6_addr *src_key = NULL;
1421 struct rt6_exception *rt6_ex;
1422 int err;
1423
1424 if (!from ||
1425 !(rt->rt6i_flags & RTF_CACHE))
1426 return -EINVAL;
1427

--- 27 unchanged lines hidden (view full) ---

1455 return err;
1456}
1457
1458/* Find rt6_ex which contains the passed in rt cache and
1459 * refresh its stamp
1460 */
1461static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
1462{
1419 struct in6_addr *src_key = NULL;
1420 struct rt6_exception *rt6_ex;
1421 int err;
1422
1423 if (!from ||
1424 !(rt->rt6i_flags & RTF_CACHE))
1425 return -EINVAL;
1426

--- 27 unchanged lines hidden (view full) ---

1454 return err;
1455}
1456
1457/* Find rt6_ex which contains the passed in rt cache and
1458 * refresh its stamp
1459 */
1460static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
1461{
1463 struct rt6_info *from = (struct rt6_info *)rt->dst.from;
1464 struct rt6_exception_bucket *bucket;
1462 struct rt6_exception_bucket *bucket;
1463 struct rt6_info *from = rt->from;
1465 struct in6_addr *src_key = NULL;
1466 struct rt6_exception *rt6_ex;
1467
1468 if (!from ||
1469 !(rt->rt6i_flags & RTF_CACHE))
1470 return;
1471
1472 rcu_read_lock();

--- 108 unchanged lines hidden (view full) ---

1581 struct rt6_info *rt = rt6_ex->rt6i;
1582
1583 /* we are pruning and obsoleting aged-out and non gateway exceptions
1584 * even if others have still references to them, so that on next
1585 * dst_check() such references can be dropped.
1586 * EXPIRES exceptions - e.g. pmtu-generated ones are pruned when
1587 * expired, independently from their aging, as per RFC 8201 section 4
1588 */
1464 struct in6_addr *src_key = NULL;
1465 struct rt6_exception *rt6_ex;
1466
1467 if (!from ||
1468 !(rt->rt6i_flags & RTF_CACHE))
1469 return;
1470
1471 rcu_read_lock();

--- 108 unchanged lines hidden (view full) ---

1580 struct rt6_info *rt = rt6_ex->rt6i;
1581
1582 /* we are pruning and obsoleting aged-out and non gateway exceptions
1583 * even if others have still references to them, so that on next
1584 * dst_check() such references can be dropped.
1585 * EXPIRES exceptions - e.g. pmtu-generated ones are pruned when
1586 * expired, independently from their aging, as per RFC 8201 section 4
1587 */
1589 if (!(rt->rt6i_flags & RTF_EXPIRES) &&
1590 time_after_eq(now, rt->dst.lastuse + gc_args->timeout)) {
1591 RT6_TRACE("aging clone %p\n", rt);
1588 if (!(rt->rt6i_flags & RTF_EXPIRES)) {
1589 if (time_after_eq(now, rt->dst.lastuse + gc_args->timeout)) {
1590 RT6_TRACE("aging clone %p\n", rt);
1591 rt6_remove_exception(bucket, rt6_ex);
1592 return;
1593 }
1594 } else if (time_after(jiffies, rt->dst.expires)) {
1595 RT6_TRACE("purging expired route %p\n", rt);
1592 rt6_remove_exception(bucket, rt6_ex);
1593 return;
1596 rt6_remove_exception(bucket, rt6_ex);
1597 return;
1594 } else if (rt->rt6i_flags & RTF_GATEWAY) {
1598 }
1599
1600 if (rt->rt6i_flags & RTF_GATEWAY) {
1595 struct neighbour *neigh;
1596 __u8 neigh_flags = 0;
1597
1598 neigh = dst_neigh_lookup(&rt->dst, &rt->rt6i_gateway);
1599 if (neigh) {
1600 neigh_flags = neigh->flags;
1601 neigh_release(neigh);
1602 }
1603 if (!(neigh_flags & NTF_ROUTER)) {
1604 RT6_TRACE("purging route %p via non-router but gateway\n",
1605 rt);
1606 rt6_remove_exception(bucket, rt6_ex);
1607 return;
1608 }
1601 struct neighbour *neigh;
1602 __u8 neigh_flags = 0;
1603
1604 neigh = dst_neigh_lookup(&rt->dst, &rt->rt6i_gateway);
1605 if (neigh) {
1606 neigh_flags = neigh->flags;
1607 neigh_release(neigh);
1608 }
1609 if (!(neigh_flags & NTF_ROUTER)) {
1610 RT6_TRACE("purging route %p via non-router but gateway\n",
1611 rt);
1612 rt6_remove_exception(bucket, rt6_ex);
1613 return;
1614 }
1609 } else if (__rt6_check_expired(rt)) {
1610 RT6_TRACE("purging expired route %p\n", rt);
1611 rt6_remove_exception(bucket, rt6_ex);
1612 return;
1613 }
1615 }
1616
1614 gc_args->more++;
1615}
1616
1617void rt6_age_exceptions(struct rt6_info *rt,
1618 struct fib6_gc_args *gc_args,
1619 unsigned long now)
1620{
1621 struct rt6_exception_bucket *bucket;

--- 197 unchanged lines hidden (view full) ---

1819
1820/* if skb is set it will be used and fl6 can be NULL */
1821u32 rt6_multipath_hash(const struct flowi6 *fl6, const struct sk_buff *skb)
1822{
1823 struct flow_keys hash_keys;
1824
1825 if (skb) {
1826 ip6_multipath_l3_keys(skb, &hash_keys);
1617 gc_args->more++;
1618}
1619
1620void rt6_age_exceptions(struct rt6_info *rt,
1621 struct fib6_gc_args *gc_args,
1622 unsigned long now)
1623{
1624 struct rt6_exception_bucket *bucket;

--- 197 unchanged lines hidden (view full) ---

1822
1823/* if skb is set it will be used and fl6 can be NULL */
1824u32 rt6_multipath_hash(const struct flowi6 *fl6, const struct sk_buff *skb)
1825{
1826 struct flow_keys hash_keys;
1827
1828 if (skb) {
1829 ip6_multipath_l3_keys(skb, &hash_keys);
1827 return flow_hash_from_keys(&hash_keys);
1830 return flow_hash_from_keys(&hash_keys) >> 1;
1828 }
1829
1831 }
1832
1830 return get_hash_from_flowi6(fl6);
1833 return get_hash_from_flowi6(fl6) >> 1;
1831}
1832
1833void ip6_route_input(struct sk_buff *skb)
1834{
1835 const struct ipv6hdr *iph = ipv6_hdr(skb);
1836 struct net *net = dev_net(skb->dev);
1837 int flags = RT6_LOOKUP_F_HAS_SADDR;
1838 struct ip_tunnel_info *tun_info;

--- 85 unchanged lines hidden (view full) ---

1924}
1925
1926/*
1927 * Destination cache support functions
1928 */
1929
1930static void rt6_dst_from_metrics_check(struct rt6_info *rt)
1931{
1834}
1835
1836void ip6_route_input(struct sk_buff *skb)
1837{
1838 const struct ipv6hdr *iph = ipv6_hdr(skb);
1839 struct net *net = dev_net(skb->dev);
1840 int flags = RT6_LOOKUP_F_HAS_SADDR;
1841 struct ip_tunnel_info *tun_info;

--- 85 unchanged lines hidden (view full) ---

1927}
1928
1929/*
1930 * Destination cache support functions
1931 */
1932
1933static void rt6_dst_from_metrics_check(struct rt6_info *rt)
1934{
1932 if (rt->dst.from &&
1933 dst_metrics_ptr(&rt->dst) != dst_metrics_ptr(rt->dst.from))
1934 dst_init_metrics(&rt->dst, dst_metrics_ptr(rt->dst.from), true);
1935 if (rt->from &&
1936 dst_metrics_ptr(&rt->dst) != dst_metrics_ptr(&rt->from->dst))
1937 dst_init_metrics(&rt->dst, dst_metrics_ptr(&rt->from->dst), true);
1935}
1936
1937static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie)
1938{
1939 u32 rt_cookie = 0;
1940
1941 if (!rt6_get_cookie_safe(rt, &rt_cookie) || rt_cookie != cookie)
1942 return NULL;
1943
1944 if (rt6_check_expired(rt))
1945 return NULL;
1946
1947 return &rt->dst;
1948}
1949
1950static struct dst_entry *rt6_dst_from_check(struct rt6_info *rt, u32 cookie)
1951{
1952 if (!__rt6_check_expired(rt) &&
1953 rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK &&
1938}
1939
1940static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie)
1941{
1942 u32 rt_cookie = 0;
1943
1944 if (!rt6_get_cookie_safe(rt, &rt_cookie) || rt_cookie != cookie)
1945 return NULL;
1946
1947 if (rt6_check_expired(rt))
1948 return NULL;
1949
1950 return &rt->dst;
1951}
1952
1953static struct dst_entry *rt6_dst_from_check(struct rt6_info *rt, u32 cookie)
1954{
1955 if (!__rt6_check_expired(rt) &&
1956 rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK &&
1954 rt6_check((struct rt6_info *)(rt->dst.from), cookie))
1957 rt6_check(rt->from, cookie))
1955 return &rt->dst;
1956 else
1957 return NULL;
1958}
1959
1960static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
1961{
1962 struct rt6_info *rt;
1963
1964 rt = (struct rt6_info *) dst;
1965
1966 /* All IPV6 dsts are created with ->obsolete set to the value
1967 * DST_OBSOLETE_FORCE_CHK which forces validation calls down
1968 * into this function always.
1969 */
1970
1971 rt6_dst_from_metrics_check(rt);
1972
1973 if (rt->rt6i_flags & RTF_PCPU ||
1958 return &rt->dst;
1959 else
1960 return NULL;
1961}
1962
1963static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
1964{
1965 struct rt6_info *rt;
1966
1967 rt = (struct rt6_info *) dst;
1968
1969 /* All IPV6 dsts are created with ->obsolete set to the value
1970 * DST_OBSOLETE_FORCE_CHK which forces validation calls down
1971 * into this function always.
1972 */
1973
1974 rt6_dst_from_metrics_check(rt);
1975
1976 if (rt->rt6i_flags & RTF_PCPU ||
1974 (unlikely(!list_empty(&rt->rt6i_uncached)) && rt->dst.from))
1977 (unlikely(!list_empty(&rt->rt6i_uncached)) && rt->from))
1975 return rt6_dst_from_check(rt, cookie);
1976 else
1977 return rt6_check(rt, cookie);
1978}
1979
1980static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
1981{
1982 struct rt6_info *rt = (struct rt6_info *) dst;

--- 166 unchanged lines hidden (view full) ---

2149 * is a bit fuzzy and one might need to check all possible
2150 * routes.
2151 */
2152
2153 rcu_read_lock();
2154 fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
2155restart:
2156 for_each_fib6_node_rt_rcu(fn) {
1978 return rt6_dst_from_check(rt, cookie);
1979 else
1980 return rt6_check(rt, cookie);
1981}
1982
1983static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
1984{
1985 struct rt6_info *rt = (struct rt6_info *) dst;

--- 166 unchanged lines hidden (view full) ---

2152 * is a bit fuzzy and one might need to check all possible
2153 * routes.
2154 */
2155
2156 rcu_read_lock();
2157 fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
2158restart:
2159 for_each_fib6_node_rt_rcu(fn) {
2160 if (rt->rt6i_nh_flags & RTNH_F_DEAD)
2161 continue;
2157 if (rt6_check_expired(rt))
2158 continue;
2159 if (rt->dst.error)
2160 break;
2161 if (!(rt->rt6i_flags & RTF_GATEWAY))
2162 continue;
2163 if (fl6->flowi6_oif != rt->dst.dev->ifindex)
2164 continue;

--- 174 unchanged lines hidden (view full) ---

2339 rt->dst.input = ip6_input;
2340 rt->dst.output = ip6_output;
2341 rt->rt6i_gateway = fl6->daddr;
2342 rt->rt6i_dst.addr = fl6->daddr;
2343 rt->rt6i_dst.plen = 128;
2344 rt->rt6i_idev = idev;
2345 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0);
2346
2162 if (rt6_check_expired(rt))
2163 continue;
2164 if (rt->dst.error)
2165 break;
2166 if (!(rt->rt6i_flags & RTF_GATEWAY))
2167 continue;
2168 if (fl6->flowi6_oif != rt->dst.dev->ifindex)
2169 continue;

--- 174 unchanged lines hidden (view full) ---

2344 rt->dst.input = ip6_input;
2345 rt->dst.output = ip6_output;
2346 rt->rt6i_gateway = fl6->daddr;
2347 rt->rt6i_dst.addr = fl6->daddr;
2348 rt->rt6i_dst.plen = 128;
2349 rt->rt6i_idev = idev;
2350 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0);
2351
2347 /* Add this dst into uncached_list so that rt6_ifdown() can
2352 /* Add this dst into uncached_list so that rt6_disable_ip() can
2348 * do proper release of the net_device
2349 */
2350 rt6_uncached_list_add(rt);
2351 atomic_inc(&net->ipv6.rt6_stats->fib_rt_uncache);
2352
2353 dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0);
2354
2355out:

--- 78 unchanged lines hidden (view full) ---

2434 return 0;
2435 err:
2436 kfree(mp);
2437 return -EINVAL;
2438}
2439
2440static struct rt6_info *ip6_nh_lookup_table(struct net *net,
2441 struct fib6_config *cfg,
2353 * do proper release of the net_device
2354 */
2355 rt6_uncached_list_add(rt);
2356 atomic_inc(&net->ipv6.rt6_stats->fib_rt_uncache);
2357
2358 dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0);
2359
2360out:

--- 78 unchanged lines hidden (view full) ---

2439 return 0;
2440 err:
2441 kfree(mp);
2442 return -EINVAL;
2443}
2444
2445static struct rt6_info *ip6_nh_lookup_table(struct net *net,
2446 struct fib6_config *cfg,
2442 const struct in6_addr *gw_addr)
2447 const struct in6_addr *gw_addr,
2448 u32 tbid, int flags)
2443{
2444 struct flowi6 fl6 = {
2445 .flowi6_oif = cfg->fc_ifindex,
2446 .daddr = *gw_addr,
2447 .saddr = cfg->fc_prefsrc,
2448 };
2449 struct fib6_table *table;
2450 struct rt6_info *rt;
2449{
2450 struct flowi6 fl6 = {
2451 .flowi6_oif = cfg->fc_ifindex,
2452 .daddr = *gw_addr,
2453 .saddr = cfg->fc_prefsrc,
2454 };
2455 struct fib6_table *table;
2456 struct rt6_info *rt;
2451 int flags = RT6_LOOKUP_F_IFACE | RT6_LOOKUP_F_IGNORE_LINKSTATE;
2452
2457
2453 table = fib6_get_table(net, cfg->fc_table);
2458 table = fib6_get_table(net, tbid);
2454 if (!table)
2455 return NULL;
2456
2457 if (!ipv6_addr_any(&cfg->fc_prefsrc))
2458 flags |= RT6_LOOKUP_F_HAS_SADDR;
2459
2459 if (!table)
2460 return NULL;
2461
2462 if (!ipv6_addr_any(&cfg->fc_prefsrc))
2463 flags |= RT6_LOOKUP_F_HAS_SADDR;
2464
2465 flags |= RT6_LOOKUP_F_IGNORE_LINKSTATE;
2460 rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, flags);
2461
2462 /* if table lookup failed, fall back to full lookup */
2463 if (rt == net->ipv6.ip6_null_entry) {
2464 ip6_rt_put(rt);
2465 rt = NULL;
2466 }
2467
2468 return rt;
2469}
2470
2466 rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, flags);
2467
2468 /* if table lookup failed, fall back to full lookup */
2469 if (rt == net->ipv6.ip6_null_entry) {
2470 ip6_rt_put(rt);
2471 rt = NULL;
2472 }
2473
2474 return rt;
2475}
2476
2477static int ip6_route_check_nh_onlink(struct net *net,
2478 struct fib6_config *cfg,
2479 struct net_device *dev,
2480 struct netlink_ext_ack *extack)
2481{
2482 u32 tbid = l3mdev_fib_table(dev) ? : RT_TABLE_LOCAL;
2483 const struct in6_addr *gw_addr = &cfg->fc_gateway;
2484 u32 flags = RTF_LOCAL | RTF_ANYCAST | RTF_REJECT;
2485 struct rt6_info *grt;
2486 int err;
2487
2488 err = 0;
2489 grt = ip6_nh_lookup_table(net, cfg, gw_addr, tbid, 0);
2490 if (grt) {
2491 if (grt->rt6i_flags & flags || dev != grt->dst.dev) {
2492 NL_SET_ERR_MSG(extack, "Nexthop has invalid gateway");
2493 err = -EINVAL;
2494 }
2495
2496 ip6_rt_put(grt);
2497 }
2498
2499 return err;
2500}
2501
2502static int ip6_route_check_nh(struct net *net,
2503 struct fib6_config *cfg,
2504 struct net_device **_dev,
2505 struct inet6_dev **idev)
2506{
2507 const struct in6_addr *gw_addr = &cfg->fc_gateway;
2508 struct net_device *dev = _dev ? *_dev : NULL;
2509 struct rt6_info *grt = NULL;
2510 int err = -EHOSTUNREACH;
2511
2512 if (cfg->fc_table) {
2513 int flags = RT6_LOOKUP_F_IFACE;
2514
2515 grt = ip6_nh_lookup_table(net, cfg, gw_addr,
2516 cfg->fc_table, flags);
2517 if (grt) {
2518 if (grt->rt6i_flags & RTF_GATEWAY ||
2519 (dev && dev != grt->dst.dev)) {
2520 ip6_rt_put(grt);
2521 grt = NULL;
2522 }
2523 }
2524 }
2525
2526 if (!grt)
2527 grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1);
2528
2529 if (!grt)
2530 goto out;
2531
2532 if (dev) {
2533 if (dev != grt->dst.dev) {
2534 ip6_rt_put(grt);
2535 goto out;
2536 }
2537 } else {
2538 *_dev = dev = grt->dst.dev;
2539 *idev = grt->rt6i_idev;
2540 dev_hold(dev);
2541 in6_dev_hold(grt->rt6i_idev);
2542 }
2543
2544 if (!(grt->rt6i_flags & RTF_GATEWAY))
2545 err = 0;
2546
2547 ip6_rt_put(grt);
2548
2549out:
2550 return err;
2551}
2552
2471static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
2472 struct netlink_ext_ack *extack)
2473{
2474 struct net *net = cfg->fc_nlinfo.nl_net;
2475 struct rt6_info *rt = NULL;
2476 struct net_device *dev = NULL;
2477 struct inet6_dev *idev = NULL;
2478 struct fib6_table *table;

--- 35 unchanged lines hidden (view full) ---

2514 idev = in6_dev_get(dev);
2515 if (!idev)
2516 goto out;
2517 }
2518
2519 if (cfg->fc_metric == 0)
2520 cfg->fc_metric = IP6_RT_PRIO_USER;
2521
2553static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
2554 struct netlink_ext_ack *extack)
2555{
2556 struct net *net = cfg->fc_nlinfo.nl_net;
2557 struct rt6_info *rt = NULL;
2558 struct net_device *dev = NULL;
2559 struct inet6_dev *idev = NULL;
2560 struct fib6_table *table;

--- 35 unchanged lines hidden (view full) ---

2596 idev = in6_dev_get(dev);
2597 if (!idev)
2598 goto out;
2599 }
2600
2601 if (cfg->fc_metric == 0)
2602 cfg->fc_metric = IP6_RT_PRIO_USER;
2603
2604 if (cfg->fc_flags & RTNH_F_ONLINK) {
2605 if (!dev) {
2606 NL_SET_ERR_MSG(extack,
2607 "Nexthop device required for onlink");
2608 err = -ENODEV;
2609 goto out;
2610 }
2611
2612 if (!(dev->flags & IFF_UP)) {
2613 NL_SET_ERR_MSG(extack, "Nexthop device is not up");
2614 err = -ENETDOWN;
2615 goto out;
2616 }
2617 }
2618
2522 err = -ENOBUFS;
2523 if (cfg->fc_nlinfo.nlh &&
2524 !(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_CREATE)) {
2525 table = fib6_get_table(net, cfg->fc_table);
2526 if (!table) {
2527 pr_warn("NLM_F_CREATE should be specified when creating new route\n");
2528 table = fib6_new_table(net, cfg->fc_table);
2529 }

--- 58 unchanged lines hidden (view full) ---

2588 rt->dst.flags |= DST_HOST;
2589
2590#ifdef CONFIG_IPV6_SUBTREES
2591 ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len);
2592 rt->rt6i_src.plen = cfg->fc_src_len;
2593#endif
2594
2595 rt->rt6i_metric = cfg->fc_metric;
2619 err = -ENOBUFS;
2620 if (cfg->fc_nlinfo.nlh &&
2621 !(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_CREATE)) {
2622 table = fib6_get_table(net, cfg->fc_table);
2623 if (!table) {
2624 pr_warn("NLM_F_CREATE should be specified when creating new route\n");
2625 table = fib6_new_table(net, cfg->fc_table);
2626 }

--- 58 unchanged lines hidden (view full) ---

2685 rt->dst.flags |= DST_HOST;
2686
2687#ifdef CONFIG_IPV6_SUBTREES
2688 ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len);
2689 rt->rt6i_src.plen = cfg->fc_src_len;
2690#endif
2691
2692 rt->rt6i_metric = cfg->fc_metric;
2693 rt->rt6i_nh_weight = 1;
2596
2597 /* We cannot add true routes via loopback here,
2598 they would result in kernel looping; promote them to reject routes
2599 */
2600 if ((cfg->fc_flags & RTF_REJECT) ||
2601 (dev && (dev->flags & IFF_LOOPBACK) &&
2602 !(addr_type & IPV6_ADDR_LOOPBACK) &&
2603 !(cfg->fc_flags & RTF_LOCAL))) {

--- 53 unchanged lines hidden (view full) ---

2657 gwa_type & IPV6_ADDR_LINKLOCAL ?
2658 dev : NULL, 0, 0)) {
2659 NL_SET_ERR_MSG(extack, "Invalid gateway address");
2660 goto out;
2661 }
2662 rt->rt6i_gateway = *gw_addr;
2663
2664 if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
2694
2695 /* We cannot add true routes via loopback here,
2696 they would result in kernel looping; promote them to reject routes
2697 */
2698 if ((cfg->fc_flags & RTF_REJECT) ||
2699 (dev && (dev->flags & IFF_LOOPBACK) &&
2700 !(addr_type & IPV6_ADDR_LOOPBACK) &&
2701 !(cfg->fc_flags & RTF_LOCAL))) {

--- 53 unchanged lines hidden (view full) ---

2755 gwa_type & IPV6_ADDR_LINKLOCAL ?
2756 dev : NULL, 0, 0)) {
2757 NL_SET_ERR_MSG(extack, "Invalid gateway address");
2758 goto out;
2759 }
2760 rt->rt6i_gateway = *gw_addr;
2761
2762 if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
2665 struct rt6_info *grt = NULL;
2666
2667 /* IPv6 strictly inhibits using not link-local
2668 addresses as nexthop address.
2669 Otherwise, router will not able to send redirects.
2670 It is very good, but in some (rare!) circumstances
2671 (SIT, PtP, NBMA NOARP links) it is handy to allow
2672 some exceptions. --ANK
2673 We allow IPv4-mapped nexthops to support RFC4798-type
2674 addressing
2675 */
2676 if (!(gwa_type & (IPV6_ADDR_UNICAST |
2677 IPV6_ADDR_MAPPED))) {
2678 NL_SET_ERR_MSG(extack,
2679 "Invalid gateway address");
2680 goto out;
2681 }
2682
2763 /* IPv6 strictly inhibits using not link-local
2764 addresses as nexthop address.
2765 Otherwise, router will not able to send redirects.
2766 It is very good, but in some (rare!) circumstances
2767 (SIT, PtP, NBMA NOARP links) it is handy to allow
2768 some exceptions. --ANK
2769 We allow IPv4-mapped nexthops to support RFC4798-type
2770 addressing
2771 */
2772 if (!(gwa_type & (IPV6_ADDR_UNICAST |
2773 IPV6_ADDR_MAPPED))) {
2774 NL_SET_ERR_MSG(extack,
2775 "Invalid gateway address");
2776 goto out;
2777 }
2778
2683 if (cfg->fc_table) {
2684 grt = ip6_nh_lookup_table(net, cfg, gw_addr);
2685
2686 if (grt) {
2687 if (grt->rt6i_flags & RTF_GATEWAY ||
2688 (dev && dev != grt->dst.dev)) {
2689 ip6_rt_put(grt);
2690 grt = NULL;
2691 }
2692 }
2693 }
2694
2695 if (!grt)
2696 grt = rt6_lookup(net, gw_addr, NULL,
2697 cfg->fc_ifindex, 1);
2698
2699 err = -EHOSTUNREACH;
2700 if (!grt)
2701 goto out;
2702 if (dev) {
2703 if (dev != grt->dst.dev) {
2704 ip6_rt_put(grt);
2705 goto out;
2706 }
2779 if (cfg->fc_flags & RTNH_F_ONLINK) {
2780 err = ip6_route_check_nh_onlink(net, cfg, dev,
2781 extack);
2707 } else {
2782 } else {
2708 dev = grt->dst.dev;
2709 idev = grt->rt6i_idev;
2710 dev_hold(dev);
2711 in6_dev_hold(grt->rt6i_idev);
2783 err = ip6_route_check_nh(net, cfg, &dev, &idev);
2712 }
2784 }
2713 if (!(grt->rt6i_flags & RTF_GATEWAY))
2714 err = 0;
2715 ip6_rt_put(grt);
2716
2717 if (err)
2718 goto out;
2719 }
2720 err = -EINVAL;
2721 if (!dev) {
2722 NL_SET_ERR_MSG(extack, "Egress device not specified");
2723 goto out;
2724 } else if (dev->flags & IFF_LOOPBACK) {
2725 NL_SET_ERR_MSG(extack,
2726 "Egress device can not be loopback device for this route");
2727 goto out;
2728 }
2729 }
2730
2731 err = -ENODEV;
2732 if (!dev)
2733 goto out;
2734
2785 if (err)
2786 goto out;
2787 }
2788 err = -EINVAL;
2789 if (!dev) {
2790 NL_SET_ERR_MSG(extack, "Egress device not specified");
2791 goto out;
2792 } else if (dev->flags & IFF_LOOPBACK) {
2793 NL_SET_ERR_MSG(extack,
2794 "Egress device can not be loopback device for this route");
2795 goto out;
2796 }
2797 }
2798
2799 err = -ENODEV;
2800 if (!dev)
2801 goto out;
2802
2803 if (!(dev->flags & IFF_UP)) {
2804 NL_SET_ERR_MSG(extack, "Nexthop device is not up");
2805 err = -ENETDOWN;
2806 goto out;
2807 }
2808
2735 if (!ipv6_addr_any(&cfg->fc_prefsrc)) {
2736 if (!ipv6_chk_addr(net, &cfg->fc_prefsrc, dev, 0)) {
2737 NL_SET_ERR_MSG(extack, "Invalid source address");
2738 err = -EINVAL;
2739 goto out;
2740 }
2741 rt->rt6i_prefsrc.addr = cfg->fc_prefsrc;
2742 rt->rt6i_prefsrc.plen = 128;
2743 } else
2744 rt->rt6i_prefsrc.plen = 0;
2745
2746 rt->rt6i_flags = cfg->fc_flags;
2747
2748install_route:
2809 if (!ipv6_addr_any(&cfg->fc_prefsrc)) {
2810 if (!ipv6_chk_addr(net, &cfg->fc_prefsrc, dev, 0)) {
2811 NL_SET_ERR_MSG(extack, "Invalid source address");
2812 err = -EINVAL;
2813 goto out;
2814 }
2815 rt->rt6i_prefsrc.addr = cfg->fc_prefsrc;
2816 rt->rt6i_prefsrc.plen = 128;
2817 } else
2818 rt->rt6i_prefsrc.plen = 0;
2819
2820 rt->rt6i_flags = cfg->fc_flags;
2821
2822install_route:
2823 if (!(rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST)) &&
2824 !netif_carrier_ok(dev))
2825 rt->rt6i_nh_flags |= RTNH_F_LINKDOWN;
2826 rt->rt6i_nh_flags |= (cfg->fc_flags & RTNH_F_ONLINK);
2749 rt->dst.dev = dev;
2750 rt->rt6i_idev = idev;
2751 rt->rt6i_table = table;
2752
2753 cfg->fc_nlinfo.nl_net = dev_net(dev);
2754
2755 return rt;
2756out:

--- 294 unchanged lines hidden (view full) ---

3051}
3052
3053/*
3054 * Misc support functions
3055 */
3056
3057static void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
3058{
2827 rt->dst.dev = dev;
2828 rt->rt6i_idev = idev;
2829 rt->rt6i_table = table;
2830
2831 cfg->fc_nlinfo.nl_net = dev_net(dev);
2832
2833 return rt;
2834out:

--- 294 unchanged lines hidden (view full) ---

3129}
3130
3131/*
3132 * Misc support functions
3133 */
3134
3135static void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
3136{
3059 BUG_ON(from->dst.from);
3137 BUG_ON(from->from);
3060
3061 rt->rt6i_flags &= ~RTF_EXPIRES;
3062 dst_hold(&from->dst);
3138
3139 rt->rt6i_flags &= ~RTF_EXPIRES;
3140 dst_hold(&from->dst);
3063 rt->dst.from = &from->dst;
3141 rt->from = from;
3064 dst_init_metrics(&rt->dst, dst_metrics_ptr(&from->dst), true);
3065}
3066
3067static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort)
3068{
3069 rt->dst.input = ort->dst.input;
3070 rt->dst.output = ort->dst.output;
3071 rt->rt6i_dst = ort->rt6i_dst;

--- 382 unchanged lines hidden (view full) ---

3454 return 0;
3455}
3456
3457void rt6_clean_tohost(struct net *net, struct in6_addr *gateway)
3458{
3459 fib6_clean_all(net, fib6_clean_tohost, gateway);
3460}
3461
3142 dst_init_metrics(&rt->dst, dst_metrics_ptr(&from->dst), true);
3143}
3144
3145static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort)
3146{
3147 rt->dst.input = ort->dst.input;
3148 rt->dst.output = ort->dst.output;
3149 rt->rt6i_dst = ort->rt6i_dst;

--- 382 unchanged lines hidden (view full) ---

3532 return 0;
3533}
3534
3535void rt6_clean_tohost(struct net *net, struct in6_addr *gateway)
3536{
3537 fib6_clean_all(net, fib6_clean_tohost, gateway);
3538}
3539
3462struct arg_dev_net {
3463 struct net_device *dev;
3464 struct net *net;
3540struct arg_netdev_event {
3541 const struct net_device *dev;
3542 union {
3543 unsigned int nh_flags;
3544 unsigned long event;
3545 };
3465};
3466
3546};
3547
3548static struct rt6_info *rt6_multipath_first_sibling(const struct rt6_info *rt)
3549{
3550 struct rt6_info *iter;
3551 struct fib6_node *fn;
3552
3553 fn = rcu_dereference_protected(rt->rt6i_node,
3554 lockdep_is_held(&rt->rt6i_table->tb6_lock));
3555 iter = rcu_dereference_protected(fn->leaf,
3556 lockdep_is_held(&rt->rt6i_table->tb6_lock));
3557 while (iter) {
3558 if (iter->rt6i_metric == rt->rt6i_metric &&
3559 rt6_qualify_for_ecmp(iter))
3560 return iter;
3561 iter = rcu_dereference_protected(iter->rt6_next,
3562 lockdep_is_held(&rt->rt6i_table->tb6_lock));
3563 }
3564
3565 return NULL;
3566}
3567
3568static bool rt6_is_dead(const struct rt6_info *rt)
3569{
3570 if (rt->rt6i_nh_flags & RTNH_F_DEAD ||
3571 (rt->rt6i_nh_flags & RTNH_F_LINKDOWN &&
3572 rt->rt6i_idev->cnf.ignore_routes_with_linkdown))
3573 return true;
3574
3575 return false;
3576}
3577
3578static int rt6_multipath_total_weight(const struct rt6_info *rt)
3579{
3580 struct rt6_info *iter;
3581 int total = 0;
3582
3583 if (!rt6_is_dead(rt))
3584 total += rt->rt6i_nh_weight;
3585
3586 list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings) {
3587 if (!rt6_is_dead(iter))
3588 total += iter->rt6i_nh_weight;
3589 }
3590
3591 return total;
3592}
3593
3594static void rt6_upper_bound_set(struct rt6_info *rt, int *weight, int total)
3595{
3596 int upper_bound = -1;
3597
3598 if (!rt6_is_dead(rt)) {
3599 *weight += rt->rt6i_nh_weight;
3600 upper_bound = DIV_ROUND_CLOSEST_ULL((u64) (*weight) << 31,
3601 total) - 1;
3602 }
3603 atomic_set(&rt->rt6i_nh_upper_bound, upper_bound);
3604}
3605
3606static void rt6_multipath_upper_bound_set(struct rt6_info *rt, int total)
3607{
3608 struct rt6_info *iter;
3609 int weight = 0;
3610
3611 rt6_upper_bound_set(rt, &weight, total);
3612
3613 list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings)
3614 rt6_upper_bound_set(iter, &weight, total);
3615}
3616
3617void rt6_multipath_rebalance(struct rt6_info *rt)
3618{
3619 struct rt6_info *first;
3620 int total;
3621
3622 /* In case the entire multipath route was marked for flushing,
3623 * then there is no need to rebalance upon the removal of every
3624 * sibling route.
3625 */
3626 if (!rt->rt6i_nsiblings || rt->should_flush)
3627 return;
3628
3629 /* During lookup routes are evaluated in order, so we need to
3630 * make sure upper bounds are assigned from the first sibling
3631 * onwards.
3632 */
3633 first = rt6_multipath_first_sibling(rt);
3634 if (WARN_ON_ONCE(!first))
3635 return;
3636
3637 total = rt6_multipath_total_weight(first);
3638 rt6_multipath_upper_bound_set(first, total);
3639}
3640
3641static int fib6_ifup(struct rt6_info *rt, void *p_arg)
3642{
3643 const struct arg_netdev_event *arg = p_arg;
3644 const struct net *net = dev_net(arg->dev);
3645
3646 if (rt != net->ipv6.ip6_null_entry && rt->dst.dev == arg->dev) {
3647 rt->rt6i_nh_flags &= ~arg->nh_flags;
3648 fib6_update_sernum_upto_root(dev_net(rt->dst.dev), rt);
3649 rt6_multipath_rebalance(rt);
3650 }
3651
3652 return 0;
3653}
3654
3655void rt6_sync_up(struct net_device *dev, unsigned int nh_flags)
3656{
3657 struct arg_netdev_event arg = {
3658 .dev = dev,
3659 {
3660 .nh_flags = nh_flags,
3661 },
3662 };
3663
3664 if (nh_flags & RTNH_F_DEAD && netif_carrier_ok(dev))
3665 arg.nh_flags |= RTNH_F_LINKDOWN;
3666
3667 fib6_clean_all(dev_net(dev), fib6_ifup, &arg);
3668}
3669
3670static bool rt6_multipath_uses_dev(const struct rt6_info *rt,
3671 const struct net_device *dev)
3672{
3673 struct rt6_info *iter;
3674
3675 if (rt->dst.dev == dev)
3676 return true;
3677 list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings)
3678 if (iter->dst.dev == dev)
3679 return true;
3680
3681 return false;
3682}
3683
3684static void rt6_multipath_flush(struct rt6_info *rt)
3685{
3686 struct rt6_info *iter;
3687
3688 rt->should_flush = 1;
3689 list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings)
3690 iter->should_flush = 1;
3691}
3692
3693static unsigned int rt6_multipath_dead_count(const struct rt6_info *rt,
3694 const struct net_device *down_dev)
3695{
3696 struct rt6_info *iter;
3697 unsigned int dead = 0;
3698
3699 if (rt->dst.dev == down_dev || rt->rt6i_nh_flags & RTNH_F_DEAD)
3700 dead++;
3701 list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings)
3702 if (iter->dst.dev == down_dev ||
3703 iter->rt6i_nh_flags & RTNH_F_DEAD)
3704 dead++;
3705
3706 return dead;
3707}
3708
3709static void rt6_multipath_nh_flags_set(struct rt6_info *rt,
3710 const struct net_device *dev,
3711 unsigned int nh_flags)
3712{
3713 struct rt6_info *iter;
3714
3715 if (rt->dst.dev == dev)
3716 rt->rt6i_nh_flags |= nh_flags;
3717 list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings)
3718 if (iter->dst.dev == dev)
3719 iter->rt6i_nh_flags |= nh_flags;
3720}
3721
3467/* called with write lock held for table with rt */
3722/* called with write lock held for table with rt */
3468static int fib6_ifdown(struct rt6_info *rt, void *arg)
3723static int fib6_ifdown(struct rt6_info *rt, void *p_arg)
3469{
3724{
3470 const struct arg_dev_net *adn = arg;
3471 const struct net_device *dev = adn->dev;
3725 const struct arg_netdev_event *arg = p_arg;
3726 const struct net_device *dev = arg->dev;
3727 const struct net *net = dev_net(dev);
3472
3728
3473 if ((rt->dst.dev == dev || !dev) &&
3474 rt != adn->net->ipv6.ip6_null_entry &&
3475 (rt->rt6i_nsiblings == 0 ||
3476 (dev && netdev_unregistering(dev)) ||
3477 !rt->rt6i_idev->cnf.ignore_routes_with_linkdown))
3478 return -1;
3729 if (rt == net->ipv6.ip6_null_entry)
3730 return 0;
3479
3731
3732 switch (arg->event) {
3733 case NETDEV_UNREGISTER:
3734 return rt->dst.dev == dev ? -1 : 0;
3735 case NETDEV_DOWN:
3736 if (rt->should_flush)
3737 return -1;
3738 if (!rt->rt6i_nsiblings)
3739 return rt->dst.dev == dev ? -1 : 0;
3740 if (rt6_multipath_uses_dev(rt, dev)) {
3741 unsigned int count;
3742
3743 count = rt6_multipath_dead_count(rt, dev);
3744 if (rt->rt6i_nsiblings + 1 == count) {
3745 rt6_multipath_flush(rt);
3746 return -1;
3747 }
3748 rt6_multipath_nh_flags_set(rt, dev, RTNH_F_DEAD |
3749 RTNH_F_LINKDOWN);
3750 fib6_update_sernum(rt);
3751 rt6_multipath_rebalance(rt);
3752 }
3753 return -2;
3754 case NETDEV_CHANGE:
3755 if (rt->dst.dev != dev ||
3756 rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST))
3757 break;
3758 rt->rt6i_nh_flags |= RTNH_F_LINKDOWN;
3759 rt6_multipath_rebalance(rt);
3760 break;
3761 }
3762
3480 return 0;
3481}
3482
3763 return 0;
3764}
3765
3483void rt6_ifdown(struct net *net, struct net_device *dev)
3766void rt6_sync_down_dev(struct net_device *dev, unsigned long event)
3484{
3767{
3485 struct arg_dev_net adn = {
3768 struct arg_netdev_event arg = {
3486 .dev = dev,
3769 .dev = dev,
3487 .net = net,
3770 {
3771 .event = event,
3772 },
3488 };
3489
3773 };
3774
3490 fib6_clean_all(net, fib6_ifdown, &adn);
3491 if (dev)
3492 rt6_uncached_list_flush_dev(net, dev);
3775 fib6_clean_all(dev_net(dev), fib6_ifdown, &arg);
3493}
3494
3776}
3777
3778void rt6_disable_ip(struct net_device *dev, unsigned long event)
3779{
3780 rt6_sync_down_dev(dev, event);
3781 rt6_uncached_list_flush_dev(dev_net(dev), dev);
3782 neigh_ifdown(&nd_tbl, dev);
3783}
3784
3495struct rt6_mtu_change_arg {
3496 struct net_device *dev;
3497 unsigned int mtu;
3498};
3499
3500static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
3501{
3502 struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg;

--- 95 unchanged lines hidden (view full) ---

3598 cfg->fc_flags |= RTF_REJECT;
3599
3600 if (rtm->rtm_type == RTN_LOCAL)
3601 cfg->fc_flags |= RTF_LOCAL;
3602
3603 if (rtm->rtm_flags & RTM_F_CLONED)
3604 cfg->fc_flags |= RTF_CACHE;
3605
3785struct rt6_mtu_change_arg {
3786 struct net_device *dev;
3787 unsigned int mtu;
3788};
3789
3790static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
3791{
3792 struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg;

--- 95 unchanged lines hidden (view full) ---

3888 cfg->fc_flags |= RTF_REJECT;
3889
3890 if (rtm->rtm_type == RTN_LOCAL)
3891 cfg->fc_flags |= RTF_LOCAL;
3892
3893 if (rtm->rtm_flags & RTM_F_CLONED)
3894 cfg->fc_flags |= RTF_CACHE;
3895
3896 cfg->fc_flags |= (rtm->rtm_flags & RTNH_F_ONLINK);
3897
3606 cfg->fc_nlinfo.portid = NETLINK_CB(skb).portid;
3607 cfg->fc_nlinfo.nlh = nlh;
3608 cfg->fc_nlinfo.nl_net = sock_net(skb->sk);
3609
3610 if (tb[RTA_GATEWAY]) {
3611 cfg->fc_gateway = nla_get_in6_addr(tb[RTA_GATEWAY]);
3612 cfg->fc_flags |= RTF_GATEWAY;
3613 }

--- 193 unchanged lines hidden (view full) ---

3807
3808 rt = ip6_route_info_create(&r_cfg, extack);
3809 if (IS_ERR(rt)) {
3810 err = PTR_ERR(rt);
3811 rt = NULL;
3812 goto cleanup;
3813 }
3814
3898 cfg->fc_nlinfo.portid = NETLINK_CB(skb).portid;
3899 cfg->fc_nlinfo.nlh = nlh;
3900 cfg->fc_nlinfo.nl_net = sock_net(skb->sk);
3901
3902 if (tb[RTA_GATEWAY]) {
3903 cfg->fc_gateway = nla_get_in6_addr(tb[RTA_GATEWAY]);
3904 cfg->fc_flags |= RTF_GATEWAY;
3905 }

--- 193 unchanged lines hidden (view full) ---

4099
4100 rt = ip6_route_info_create(&r_cfg, extack);
4101 if (IS_ERR(rt)) {
4102 err = PTR_ERR(rt);
4103 rt = NULL;
4104 goto cleanup;
4105 }
4106
4107 rt->rt6i_nh_weight = rtnh->rtnh_hops + 1;
4108
3815 err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg);
3816 if (err) {
3817 dst_release_immediate(&rt->dst);
3818 goto cleanup;
3819 }
3820
3821 rtnh = rtnh_next(rtnh, &remaining);
3822 }

--- 164 unchanged lines hidden (view full) ---

3987 + nla_total_size(1) /* RTA_PREF */
3988 + lwtunnel_get_encap_size(rt->dst.lwtstate)
3989 + nexthop_len;
3990}
3991
3992static int rt6_nexthop_info(struct sk_buff *skb, struct rt6_info *rt,
3993 unsigned int *flags, bool skip_oif)
3994{
4109 err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg);
4110 if (err) {
4111 dst_release_immediate(&rt->dst);
4112 goto cleanup;
4113 }
4114
4115 rtnh = rtnh_next(rtnh, &remaining);
4116 }

--- 164 unchanged lines hidden (view full) ---

4281 + nla_total_size(1) /* RTA_PREF */
4282 + lwtunnel_get_encap_size(rt->dst.lwtstate)
4283 + nexthop_len;
4284}
4285
4286static int rt6_nexthop_info(struct sk_buff *skb, struct rt6_info *rt,
4287 unsigned int *flags, bool skip_oif)
4288{
3995 if (!netif_running(rt->dst.dev) || !netif_carrier_ok(rt->dst.dev)) {
4289 if (rt->rt6i_nh_flags & RTNH_F_DEAD)
4290 *flags |= RTNH_F_DEAD;
4291
4292 if (rt->rt6i_nh_flags & RTNH_F_LINKDOWN) {
3996 *flags |= RTNH_F_LINKDOWN;
3997 if (rt->rt6i_idev->cnf.ignore_routes_with_linkdown)
3998 *flags |= RTNH_F_DEAD;
3999 }
4000
4001 if (rt->rt6i_flags & RTF_GATEWAY) {
4002 if (nla_put_in6_addr(skb, RTA_GATEWAY, &rt->rt6i_gateway) < 0)
4003 goto nla_put_failure;
4004 }
4005
4293 *flags |= RTNH_F_LINKDOWN;
4294 if (rt->rt6i_idev->cnf.ignore_routes_with_linkdown)
4295 *flags |= RTNH_F_DEAD;
4296 }
4297
4298 if (rt->rt6i_flags & RTF_GATEWAY) {
4299 if (nla_put_in6_addr(skb, RTA_GATEWAY, &rt->rt6i_gateway) < 0)
4300 goto nla_put_failure;
4301 }
4302
4303 *flags |= (rt->rt6i_nh_flags & RTNH_F_ONLINK);
4006 if (rt->rt6i_nh_flags & RTNH_F_OFFLOAD)
4007 *flags |= RTNH_F_OFFLOAD;
4008
4009 /* not needed for multipath encoding b/c it has a rtnexthop struct */
4010 if (!skip_oif && rt->dst.dev &&
4011 nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex))
4012 goto nla_put_failure;
4013

--- 12 unchanged lines hidden (view full) ---

4026{
4027 struct rtnexthop *rtnh;
4028 unsigned int flags = 0;
4029
4030 rtnh = nla_reserve_nohdr(skb, sizeof(*rtnh));
4031 if (!rtnh)
4032 goto nla_put_failure;
4033
4304 if (rt->rt6i_nh_flags & RTNH_F_OFFLOAD)
4305 *flags |= RTNH_F_OFFLOAD;
4306
4307 /* not needed for multipath encoding b/c it has a rtnexthop struct */
4308 if (!skip_oif && rt->dst.dev &&
4309 nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex))
4310 goto nla_put_failure;
4311

--- 12 unchanged lines hidden (view full) ---

4324{
4325 struct rtnexthop *rtnh;
4326 unsigned int flags = 0;
4327
4328 rtnh = nla_reserve_nohdr(skb, sizeof(*rtnh));
4329 if (!rtnh)
4330 goto nla_put_failure;
4331
4034 rtnh->rtnh_hops = 0;
4332 rtnh->rtnh_hops = rt->rt6i_nh_weight - 1;
4035 rtnh->rtnh_ifindex = rt->dst.dev ? rt->dst.dev->ifindex : 0;
4036
4037 if (rt6_nexthop_info(skb, rt, &flags, true) < 0)
4038 goto nla_put_failure;
4039
4040 rtnh->rtnh_flags = flags;
4041
4042 /* length of rtnetlink header + attributes */

--- 273 unchanged lines hidden (view full) ---

4316 }
4317
4318 if (rt == net->ipv6.ip6_null_entry) {
4319 err = rt->dst.error;
4320 ip6_rt_put(rt);
4321 goto errout;
4322 }
4323
4333 rtnh->rtnh_ifindex = rt->dst.dev ? rt->dst.dev->ifindex : 0;
4334
4335 if (rt6_nexthop_info(skb, rt, &flags, true) < 0)
4336 goto nla_put_failure;
4337
4338 rtnh->rtnh_flags = flags;
4339
4340 /* length of rtnetlink header + attributes */

--- 273 unchanged lines hidden (view full) ---

4614 }
4615
4616 if (rt == net->ipv6.ip6_null_entry) {
4617 err = rt->dst.error;
4618 ip6_rt_put(rt);
4619 goto errout;
4620 }
4621
4324 if (fibmatch && rt->dst.from) {
4325 struct rt6_info *ort = container_of(rt->dst.from,
4326 struct rt6_info, dst);
4622 if (fibmatch && rt->from) {
4623 struct rt6_info *ort = rt->from;
4327
4328 dst_hold(&ort->dst);
4329 ip6_rt_put(rt);
4330 rt = ort;
4331 }
4332
4333 skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
4334 if (!skb) {

--- 87 unchanged lines hidden (view full) ---

4422
4423/*
4424 * /proc
4425 */
4426
4427#ifdef CONFIG_PROC_FS
4428
4429static const struct file_operations ipv6_route_proc_fops = {
4624
4625 dst_hold(&ort->dst);
4626 ip6_rt_put(rt);
4627 rt = ort;
4628 }
4629
4630 skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
4631 if (!skb) {

--- 87 unchanged lines hidden (view full) ---

4719
4720/*
4721 * /proc
4722 */
4723
4724#ifdef CONFIG_PROC_FS
4725
4726static const struct file_operations ipv6_route_proc_fops = {
4430 .owner = THIS_MODULE,
4431 .open = ipv6_route_open,
4432 .read = seq_read,
4433 .llseek = seq_lseek,
4434 .release = seq_release_net,
4435};
4436
4437static int rt6_stats_seq_show(struct seq_file *seq, void *v)
4438{

--- 11 unchanged lines hidden (view full) ---

4450}
4451
4452static int rt6_stats_seq_open(struct inode *inode, struct file *file)
4453{
4454 return single_open_net(inode, file, rt6_stats_seq_show);
4455}
4456
4457static const struct file_operations rt6_stats_seq_fops = {
4727 .open = ipv6_route_open,
4728 .read = seq_read,
4729 .llseek = seq_lseek,
4730 .release = seq_release_net,
4731};
4732
4733static int rt6_stats_seq_show(struct seq_file *seq, void *v)
4734{

--- 11 unchanged lines hidden (view full) ---

4746}
4747
4748static int rt6_stats_seq_open(struct inode *inode, struct file *file)
4749{
4750 return single_open_net(inode, file, rt6_stats_seq_show);
4751}
4752
4753static const struct file_operations rt6_stats_seq_fops = {
4458 .owner = THIS_MODULE,
4459 .open = rt6_stats_seq_open,
4460 .read = seq_read,
4461 .llseek = seq_lseek,
4462 .release = single_release_net,
4463};
4464#endif /* CONFIG_PROC_FS */
4465
4466#ifdef CONFIG_SYSCTL

--- 128 unchanged lines hidden (view full) ---

4595 if (dst_entries_init(&net->ipv6.ip6_dst_ops) < 0)
4596 goto out_ip6_dst_ops;
4597
4598 net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template,
4599 sizeof(*net->ipv6.ip6_null_entry),
4600 GFP_KERNEL);
4601 if (!net->ipv6.ip6_null_entry)
4602 goto out_ip6_dst_entries;
4754 .open = rt6_stats_seq_open,
4755 .read = seq_read,
4756 .llseek = seq_lseek,
4757 .release = single_release_net,
4758};
4759#endif /* CONFIG_PROC_FS */
4760
4761#ifdef CONFIG_SYSCTL

--- 128 unchanged lines hidden (view full) ---

4890 if (dst_entries_init(&net->ipv6.ip6_dst_ops) < 0)
4891 goto out_ip6_dst_ops;
4892
4893 net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template,
4894 sizeof(*net->ipv6.ip6_null_entry),
4895 GFP_KERNEL);
4896 if (!net->ipv6.ip6_null_entry)
4897 goto out_ip6_dst_entries;
4603 net->ipv6.ip6_null_entry->dst.path =
4604 (struct dst_entry *)net->ipv6.ip6_null_entry;
4605 net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops;
4606 dst_init_metrics(&net->ipv6.ip6_null_entry->dst,
4607 ip6_template_metrics, true);
4608
4609#ifdef CONFIG_IPV6_MULTIPLE_TABLES
4610 net->ipv6.fib6_has_custom_rules = false;
4611 net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
4612 sizeof(*net->ipv6.ip6_prohibit_entry),
4613 GFP_KERNEL);
4614 if (!net->ipv6.ip6_prohibit_entry)
4615 goto out_ip6_null_entry;
4898 net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops;
4899 dst_init_metrics(&net->ipv6.ip6_null_entry->dst,
4900 ip6_template_metrics, true);
4901
4902#ifdef CONFIG_IPV6_MULTIPLE_TABLES
4903 net->ipv6.fib6_has_custom_rules = false;
4904 net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
4905 sizeof(*net->ipv6.ip6_prohibit_entry),
4906 GFP_KERNEL);
4907 if (!net->ipv6.ip6_prohibit_entry)
4908 goto out_ip6_null_entry;
4616 net->ipv6.ip6_prohibit_entry->dst.path =
4617 (struct dst_entry *)net->ipv6.ip6_prohibit_entry;
4618 net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops;
4619 dst_init_metrics(&net->ipv6.ip6_prohibit_entry->dst,
4620 ip6_template_metrics, true);
4621
4622 net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
4623 sizeof(*net->ipv6.ip6_blk_hole_entry),
4624 GFP_KERNEL);
4625 if (!net->ipv6.ip6_blk_hole_entry)
4626 goto out_ip6_prohibit_entry;
4909 net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops;
4910 dst_init_metrics(&net->ipv6.ip6_prohibit_entry->dst,
4911 ip6_template_metrics, true);
4912
4913 net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
4914 sizeof(*net->ipv6.ip6_blk_hole_entry),
4915 GFP_KERNEL);
4916 if (!net->ipv6.ip6_blk_hole_entry)
4917 goto out_ip6_prohibit_entry;
4627 net->ipv6.ip6_blk_hole_entry->dst.path =
4628 (struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
4629 net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
4630 dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
4631 ip6_template_metrics, true);
4632#endif
4633
4634 net->ipv6.sysctl.flush_delay = 0;
4635 net->ipv6.sysctl.ip6_rt_max_size = 4096;
4636 net->ipv6.sysctl.ip6_rt_gc_min_interval = HZ / 2;

--- 140 unchanged lines hidden (view full) ---

4777 ret = fib6_rules_init();
4778 if (ret)
4779 goto xfrm6_init;
4780
4781 ret = register_pernet_subsys(&ip6_route_net_late_ops);
4782 if (ret)
4783 goto fib6_rules_init;
4784
4918 net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
4919 dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
4920 ip6_template_metrics, true);
4921#endif
4922
4923 net->ipv6.sysctl.flush_delay = 0;
4924 net->ipv6.sysctl.ip6_rt_max_size = 4096;
4925 net->ipv6.sysctl.ip6_rt_gc_min_interval = HZ / 2;

--- 140 unchanged lines hidden (view full) ---

5066 ret = fib6_rules_init();
5067 if (ret)
5068 goto xfrm6_init;
5069
5070 ret = register_pernet_subsys(&ip6_route_net_late_ops);
5071 if (ret)
5072 goto fib6_rules_init;
5073
4785 ret = -ENOBUFS;
4786 if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, 0) ||
4787 __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, 0) ||
4788 __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL,
4789 RTNL_FLAG_DOIT_UNLOCKED))
5074 ret = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_NEWROUTE,
5075 inet6_rtm_newroute, NULL, 0);
5076 if (ret < 0)
4790 goto out_register_late_subsys;
4791
5077 goto out_register_late_subsys;
5078
5079 ret = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_DELROUTE,
5080 inet6_rtm_delroute, NULL, 0);
5081 if (ret < 0)
5082 goto out_register_late_subsys;
5083
5084 ret = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETROUTE,
5085 inet6_rtm_getroute, NULL,
5086 RTNL_FLAG_DOIT_UNLOCKED);
5087 if (ret < 0)
5088 goto out_register_late_subsys;
5089
4792 ret = register_netdevice_notifier(&ip6_route_dev_notifier);
4793 if (ret)
4794 goto out_register_late_subsys;
4795
4796 for_each_possible_cpu(cpu) {
4797 struct uncached_list *ul = per_cpu_ptr(&rt6_uncached_list, cpu);
4798
4799 INIT_LIST_HEAD(&ul->head);
4800 spin_lock_init(&ul->lock);
4801 }
4802
4803out:
4804 return ret;
4805
4806out_register_late_subsys:
5090 ret = register_netdevice_notifier(&ip6_route_dev_notifier);
5091 if (ret)
5092 goto out_register_late_subsys;
5093
5094 for_each_possible_cpu(cpu) {
5095 struct uncached_list *ul = per_cpu_ptr(&rt6_uncached_list, cpu);
5096
5097 INIT_LIST_HEAD(&ul->head);
5098 spin_lock_init(&ul->lock);
5099 }
5100
5101out:
5102 return ret;
5103
5104out_register_late_subsys:
5105 rtnl_unregister_all(PF_INET6);
4807 unregister_pernet_subsys(&ip6_route_net_late_ops);
4808fib6_rules_init:
4809 fib6_rules_cleanup();
4810xfrm6_init:
4811 xfrm6_fini();
4812out_fib6_init:
4813 fib6_gc_cleanup();
4814out_register_subsys:

--- 22 unchanged lines hidden ---
5106 unregister_pernet_subsys(&ip6_route_net_late_ops);
5107fib6_rules_init:
5108 fib6_rules_cleanup();
5109xfrm6_init:
5110 xfrm6_fini();
5111out_fib6_init:
5112 fib6_gc_cleanup();
5113out_register_subsys:

--- 22 unchanged lines hidden ---