route.c (f43dc23d5ea91fca257be02138a255f02d98e806) | route.c (c7066f70d9610df0b9406cc635fc09e86136e714) |
---|---|
1/* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * ROUTE - implementation of the IP router. 7 * 8 * Authors: Ross Biro --- 125 unchanged lines hidden (view full) --- 134static struct delayed_work expires_work; 135static unsigned long expires_ljiffies; 136 137/* 138 * Interface to generic destination cache. 139 */ 140 141static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie); | 1/* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * ROUTE - implementation of the IP router. 7 * 8 * Authors: Ross Biro --- 125 unchanged lines hidden (view full) --- 134static struct delayed_work expires_work; 135static unsigned long expires_ljiffies; 136 137/* 138 * Interface to generic destination cache. 139 */ 140 141static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie); |
142static unsigned int ipv4_default_advmss(const struct dst_entry *dst); 143static unsigned int ipv4_default_mtu(const struct dst_entry *dst); | |
144static void ipv4_dst_destroy(struct dst_entry *dst); 145static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); 146static void ipv4_link_failure(struct sk_buff *skb); 147static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu); 148static int rt_garbage_collect(struct dst_ops *ops); 149 150static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev, 151 int how) 152{ 153} 154 155static struct dst_ops ipv4_dst_ops = { 156 .family = AF_INET, 157 .protocol = cpu_to_be16(ETH_P_IP), 158 .gc = rt_garbage_collect, 159 .check = ipv4_dst_check, | 142static void ipv4_dst_destroy(struct dst_entry *dst); 143static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); 144static void ipv4_link_failure(struct sk_buff *skb); 145static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu); 146static int rt_garbage_collect(struct dst_ops *ops); 147 148static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev, 149 int how) 150{ 151} 152 153static struct dst_ops ipv4_dst_ops = { 154 .family = AF_INET, 155 .protocol = cpu_to_be16(ETH_P_IP), 156 .gc = rt_garbage_collect, 157 .check = ipv4_dst_check, |
160 .default_advmss = ipv4_default_advmss, 161 .default_mtu = ipv4_default_mtu, | |
162 .destroy = ipv4_dst_destroy, 163 .ifdown = ipv4_dst_ifdown, 164 .negative_advice = ipv4_negative_advice, 165 .link_failure = ipv4_link_failure, 166 .update_pmtu = ip_rt_update_pmtu, 167 .local_out = __ip_local_out, 168}; 169 --- 212 unchanged lines hidden (view full) --- 382 383 seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t" 384 "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", 385 r->dst.dev ? r->dst.dev->name : "*", 386 (__force u32)r->rt_dst, 387 (__force u32)r->rt_gateway, 388 r->rt_flags, atomic_read(&r->dst.__refcnt), 389 r->dst.__use, 0, (__force u32)r->rt_src, | 158 .destroy = ipv4_dst_destroy, 159 .ifdown = ipv4_dst_ifdown, 160 .negative_advice = ipv4_negative_advice, 161 .link_failure = ipv4_link_failure, 162 .update_pmtu = ip_rt_update_pmtu, 163 .local_out = __ip_local_out, 164}; 165 --- 212 unchanged lines hidden (view full) --- 378 379 seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t" 380 "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", 381 r->dst.dev ? r->dst.dev->name : "*", 382 (__force u32)r->rt_dst, 383 (__force u32)r->rt_gateway, 384 r->rt_flags, atomic_read(&r->dst.__refcnt), 385 r->dst.__use, 0, (__force u32)r->rt_src, |
390 dst_metric_advmss(&r->dst) + 40, | 386 (dst_metric(&r->dst, RTAX_ADVMSS) ? 387 (int)dst_metric(&r->dst, RTAX_ADVMSS) + 40 : 0), |
391 dst_metric(&r->dst, RTAX_WINDOW), 392 (int)((dst_metric(&r->dst, RTAX_RTT) >> 3) + 393 dst_metric(&r->dst, RTAX_RTTVAR)), 394 r->fl.fl4_tos, 395 r->dst.hh ? atomic_read(&r->dst.hh->hh_refcnt) : -1, 396 r->dst.hh ? (r->dst.hh->hh_output == 397 dev_queue_xmit) : 0, 398 r->rt_spec_dst, &len); --- 110 unchanged lines hidden (view full) --- 509static const struct file_operations rt_cpu_seq_fops = { 510 .owner = THIS_MODULE, 511 .open = rt_cpu_seq_open, 512 .read = seq_read, 513 .llseek = seq_lseek, 514 .release = seq_release, 515}; 516 | 388 dst_metric(&r->dst, RTAX_WINDOW), 389 (int)((dst_metric(&r->dst, RTAX_RTT) >> 3) + 390 dst_metric(&r->dst, RTAX_RTTVAR)), 391 r->fl.fl4_tos, 392 r->dst.hh ? atomic_read(&r->dst.hh->hh_refcnt) : -1, 393 r->dst.hh ? (r->dst.hh->hh_output == 394 dev_queue_xmit) : 0, 395 r->rt_spec_dst, &len); --- 110 unchanged lines hidden (view full) --- 506static const struct file_operations rt_cpu_seq_fops = { 507 .owner = THIS_MODULE, 508 .open = rt_cpu_seq_open, 509 .read = seq_read, 510 .llseek = seq_lseek, 511 .release = seq_release, 512}; 513 |
517#ifdef CONFIG_NET_CLS_ROUTE | 514#ifdef CONFIG_IP_ROUTE_CLASSID |
518static int rt_acct_proc_show(struct seq_file *m, void *v) 519{ 520 struct ip_rt_acct *dst, *src; 521 unsigned int i, j; 522 523 dst = kcalloc(256, sizeof(struct ip_rt_acct), GFP_KERNEL); 524 if (!dst) 525 return -ENOMEM; --- 36 unchanged lines hidden (view full) --- 562 if (!pde) 563 goto err1; 564 565 pde = proc_create("rt_cache", S_IRUGO, 566 net->proc_net_stat, &rt_cpu_seq_fops); 567 if (!pde) 568 goto err2; 569 | 515static int rt_acct_proc_show(struct seq_file *m, void *v) 516{ 517 struct ip_rt_acct *dst, *src; 518 unsigned int i, j; 519 520 dst = kcalloc(256, sizeof(struct ip_rt_acct), GFP_KERNEL); 521 if (!dst) 522 return -ENOMEM; --- 36 unchanged lines hidden (view full) --- 559 if (!pde) 560 goto err1; 561 562 pde = proc_create("rt_cache", S_IRUGO, 563 net->proc_net_stat, &rt_cpu_seq_fops); 564 if (!pde) 565 goto err2; 566 |
570#ifdef CONFIG_NET_CLS_ROUTE | 567#ifdef CONFIG_IP_ROUTE_CLASSID |
571 pde = proc_create("rt_acct", 0, net->proc_net, &rt_acct_proc_fops); 572 if (!pde) 573 goto err3; 574#endif 575 return 0; 576 | 568 pde = proc_create("rt_acct", 0, net->proc_net, &rt_acct_proc_fops); 569 if (!pde) 570 goto err3; 571#endif 572 return 0; 573 |
577#ifdef CONFIG_NET_CLS_ROUTE | 574#ifdef CONFIG_IP_ROUTE_CLASSID |
578err3: 579 remove_proc_entry("rt_cache", net->proc_net_stat); 580#endif 581err2: 582 remove_proc_entry("rt_cache", net->proc_net); 583err1: 584 return -ENOMEM; 585} 586 587static void __net_exit ip_rt_do_proc_exit(struct net *net) 588{ 589 remove_proc_entry("rt_cache", net->proc_net_stat); 590 remove_proc_entry("rt_cache", net->proc_net); | 575err3: 576 remove_proc_entry("rt_cache", net->proc_net_stat); 577#endif 578err2: 579 remove_proc_entry("rt_cache", net->proc_net); 580err1: 581 return -ENOMEM; 582} 583 584static void __net_exit ip_rt_do_proc_exit(struct net *net) 585{ 586 remove_proc_entry("rt_cache", net->proc_net_stat); 587 remove_proc_entry("rt_cache", net->proc_net); |
591#ifdef CONFIG_NET_CLS_ROUTE | 588#ifdef CONFIG_IP_ROUTE_CLASSID |
592 remove_proc_entry("rt_acct", net->proc_net); 593#endif 594} 595 596static struct pernet_operations ip_rt_proc_ops __net_initdata = { 597 .init = ip_rt_do_proc_init, 598 .exit = ip_rt_do_proc_exit, 599}; --- 82 unchanged lines hidden (view full) --- 682{ 683 return net->ipv4.current_rt_cache_rebuild_count <= 684 net->ipv4.sysctl_rt_cache_rebuild_count; 685} 686 687static inline bool compare_hash_inputs(const struct flowi *fl1, 688 const struct flowi *fl2) 689{ | 589 remove_proc_entry("rt_acct", net->proc_net); 590#endif 591} 592 593static struct pernet_operations ip_rt_proc_ops __net_initdata = { 594 .init = ip_rt_do_proc_init, 595 .exit = ip_rt_do_proc_exit, 596}; --- 82 unchanged lines hidden (view full) --- 679{ 680 return net->ipv4.current_rt_cache_rebuild_count <= 681 net->ipv4.sysctl_rt_cache_rebuild_count; 682} 683 684static inline bool compare_hash_inputs(const struct flowi *fl1, 685 const struct flowi *fl2) 686{ |
690 return ((((__force u32)fl1->fl4_dst ^ (__force u32)fl2->fl4_dst) | 691 ((__force u32)fl1->fl4_src ^ (__force u32)fl2->fl4_src) | | 687 return ((((__force u32)fl1->nl_u.ip4_u.daddr ^ (__force u32)fl2->nl_u.ip4_u.daddr) | 688 ((__force u32)fl1->nl_u.ip4_u.saddr ^ (__force u32)fl2->nl_u.ip4_u.saddr) | |
692 (fl1->iif ^ fl2->iif)) == 0); 693} 694 695static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) 696{ | 689 (fl1->iif ^ fl2->iif)) == 0); 690} 691 692static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) 693{ |
697 return (((__force u32)fl1->fl4_dst ^ (__force u32)fl2->fl4_dst) | 698 ((__force u32)fl1->fl4_src ^ (__force u32)fl2->fl4_src) | | 694 return (((__force u32)fl1->nl_u.ip4_u.daddr ^ (__force u32)fl2->nl_u.ip4_u.daddr) | 695 ((__force u32)fl1->nl_u.ip4_u.saddr ^ (__force u32)fl2->nl_u.ip4_u.saddr) | |
699 (fl1->mark ^ fl2->mark) | | 696 (fl1->mark ^ fl2->mark) | |
700 (*(u16 *)&fl1->fl4_tos ^ *(u16 *)&fl2->fl4_tos) | | 697 (*(u16 *)&fl1->nl_u.ip4_u.tos ^ *(u16 *)&fl2->nl_u.ip4_u.tos) | |
701 (fl1->oif ^ fl2->oif) | 702 (fl1->iif ^ fl2->iif)) == 0; 703} 704 705static inline int compare_netns(struct rtable *rt1, struct rtable *rt2) 706{ 707 return net_eq(dev_net(rt1->dst.dev), dev_net(rt2->dst.dev)); 708} 709 710static inline int rt_is_expired(struct rtable *rth) 711{ 712 return rth->rt_genid != rt_genid(dev_net(rth->dst.dev)); 713} 714 715/* 716 * Perform a full scan of hash table and free all entries. 717 * Can be called by a softirq or a process. 718 * In the later case, we want to be reschedule if necessary 719 */ | 698 (fl1->oif ^ fl2->oif) | 699 (fl1->iif ^ fl2->iif)) == 0; 700} 701 702static inline int compare_netns(struct rtable *rt1, struct rtable *rt2) 703{ 704 return net_eq(dev_net(rt1->dst.dev), dev_net(rt2->dst.dev)); 705} 706 707static inline int rt_is_expired(struct rtable *rth) 708{ 709 return rth->rt_genid != rt_genid(dev_net(rth->dst.dev)); 710} 711 712/* 713 * Perform a full scan of hash table and free all entries. 714 * Can be called by a softirq or a process. 715 * In the later case, we want to be reschedule if necessary 716 */ |
720static void rt_do_flush(struct net *net, int process_context) | 717static void rt_do_flush(int process_context) |
721{ 722 unsigned int i; 723 struct rtable *rth, *next; | 718{ 719 unsigned int i; 720 struct rtable *rth, *next; |
721 struct rtable * tail; |
|
724 725 for (i = 0; i <= rt_hash_mask; i++) { | 722 723 for (i = 0; i <= rt_hash_mask; i++) { |
726 struct rtable __rcu **pprev; 727 struct rtable *list; 728 | |
729 if (process_context && need_resched()) 730 cond_resched(); 731 rth = rcu_dereference_raw(rt_hash_table[i].chain); 732 if (!rth) 733 continue; 734 735 spin_lock_bh(rt_hash_lock_addr(i)); | 724 if (process_context && need_resched()) 725 cond_resched(); 726 rth = rcu_dereference_raw(rt_hash_table[i].chain); 727 if (!rth) 728 continue; 729 730 spin_lock_bh(rt_hash_lock_addr(i)); |
731#ifdef CONFIG_NET_NS 732 { 733 struct rtable __rcu **prev; 734 struct rtable *p; |
|
736 | 735 |
737 list = NULL; 738 pprev = &rt_hash_table[i].chain; 739 rth = rcu_dereference_protected(*pprev, | 736 rth = rcu_dereference_protected(rt_hash_table[i].chain, |
740 lockdep_is_held(rt_hash_lock_addr(i))); 741 | 737 lockdep_is_held(rt_hash_lock_addr(i))); 738 |
742 while (rth) { 743 next = rcu_dereference_protected(rth->dst.rt_next, 744 lockdep_is_held(rt_hash_lock_addr(i))); | 739 /* defer releasing the head of the list after spin_unlock */ 740 for (tail = rth; tail; 741 tail = rcu_dereference_protected(tail->dst.rt_next, 742 lockdep_is_held(rt_hash_lock_addr(i)))) 743 if (!rt_is_expired(tail)) 744 break; 745 if (rth != tail) 746 rt_hash_table[i].chain = tail; |
745 | 747 |
746 if (!net || 747 net_eq(dev_net(rth->dst.dev), net)) { 748 rcu_assign_pointer(*pprev, next); 749 rcu_assign_pointer(rth->dst.rt_next, list); 750 list = rth; | 748 /* call rt_free on entries after the tail requiring flush */ 749 prev = &rt_hash_table[i].chain; 750 for (p = rcu_dereference_protected(*prev, 751 lockdep_is_held(rt_hash_lock_addr(i))); 752 p != NULL; 753 p = next) { 754 next = rcu_dereference_protected(p->dst.rt_next, 755 lockdep_is_held(rt_hash_lock_addr(i))); 756 if (!rt_is_expired(p)) { 757 prev = &p->dst.rt_next; |
751 } else { | 758 } else { |
752 pprev = &rth->dst.rt_next; | 759 *prev = next; 760 rt_free(p); |
753 } | 761 } |
754 rth = next; | |
755 } | 762 } |
756 | 763 } 764#else 765 rth = rcu_dereference_protected(rt_hash_table[i].chain, 766 lockdep_is_held(rt_hash_lock_addr(i))); 767 rcu_assign_pointer(rt_hash_table[i].chain, NULL); 768 tail = NULL; 769#endif |
757 spin_unlock_bh(rt_hash_lock_addr(i)); 758 | 770 spin_unlock_bh(rt_hash_lock_addr(i)); 771 |
759 for (; list; list = next) { 760 next = rcu_dereference_protected(list->dst.rt_next, 1); 761 rt_free(list); | 772 for (; rth != tail; rth = next) { 773 next = rcu_dereference_protected(rth->dst.rt_next, 1); 774 rt_free(rth); |
762 } 763 } 764} 765 766/* 767 * While freeing expired entries, we compute average chain length 768 * and standard deviation, using fixed-point arithmetic. 769 * This to have an estimation of rt_chain_length_max --- 131 unchanged lines hidden (view full) --- 901/* 902 * delay < 0 : invalidate cache (fast : entries will be deleted later) 903 * delay >= 0 : invalidate & flush cache (can be long) 904 */ 905void rt_cache_flush(struct net *net, int delay) 906{ 907 rt_cache_invalidate(net); 908 if (delay >= 0) | 775 } 776 } 777} 778 779/* 780 * While freeing expired entries, we compute average chain length 781 * and standard deviation, using fixed-point arithmetic. 782 * This to have an estimation of rt_chain_length_max --- 131 unchanged lines hidden (view full) --- 914/* 915 * delay < 0 : invalidate cache (fast : entries will be deleted later) 916 * delay >= 0 : invalidate & flush cache (can be long) 917 */ 918void rt_cache_flush(struct net *net, int delay) 919{ 920 rt_cache_invalidate(net); 921 if (delay >= 0) |
909 rt_do_flush(net, !in_softirq()); | 922 rt_do_flush(!in_softirq()); |
910} 911 912/* Flush previous cache invalidated entries from the cache */ | 923} 924 925/* Flush previous cache invalidated entries from the cache */ |
913void rt_cache_flush_batch(struct net *net) | 926void rt_cache_flush_batch(void) |
914{ | 927{ |
915 rt_do_flush(net, !in_softirq()); | 928 rt_do_flush(!in_softirq()); |
916} 917 918static void rt_emergency_hash_rebuild(struct net *net) 919{ 920 if (net_ratelimit()) 921 printk(KERN_WARNING "Route hash chain too long!\n"); 922 rt_cache_invalidate(net); 923} --- 347 unchanged lines hidden (view full) --- 1271 skb_dst_set(skb, &rt->dst); 1272 return 0; 1273} 1274 1275void rt_bind_peer(struct rtable *rt, int create) 1276{ 1277 struct inet_peer *peer; 1278 | 929} 930 931static void rt_emergency_hash_rebuild(struct net *net) 932{ 933 if (net_ratelimit()) 934 printk(KERN_WARNING "Route hash chain too long!\n"); 935 rt_cache_invalidate(net); 936} --- 347 unchanged lines hidden (view full) --- 1284 skb_dst_set(skb, &rt->dst); 1285 return 0; 1286} 1287 1288void rt_bind_peer(struct rtable *rt, int create) 1289{ 1290 struct inet_peer *peer; 1291 |
1279 peer = inet_getpeer_v4(rt->rt_dst, create); | 1292 peer = inet_getpeer(rt->rt_dst, create); |
1280 1281 if (peer && cmpxchg(&rt->peer, NULL, peer) != NULL) 1282 inet_putpeer(peer); 1283} 1284 1285/* 1286 * Peer allocation may fail only in serious out-of-memory conditions. However 1287 * we still can generate some output. --- 380 unchanged lines hidden (view full) --- 1668 old_mtu -= iph->ihl << 2; 1669 1670 mtu = guess_mtu(old_mtu); 1671 } 1672 if (mtu <= dst_mtu(&rth->dst)) { 1673 if (mtu < dst_mtu(&rth->dst)) { 1674 dst_confirm(&rth->dst); 1675 if (mtu < ip_rt_min_pmtu) { | 1293 1294 if (peer && cmpxchg(&rt->peer, NULL, peer) != NULL) 1295 inet_putpeer(peer); 1296} 1297 1298/* 1299 * Peer allocation may fail only in serious out-of-memory conditions. However 1300 * we still can generate some output. --- 380 unchanged lines hidden (view full) --- 1681 old_mtu -= iph->ihl << 2; 1682 1683 mtu = guess_mtu(old_mtu); 1684 } 1685 if (mtu <= dst_mtu(&rth->dst)) { 1686 if (mtu < dst_mtu(&rth->dst)) { 1687 dst_confirm(&rth->dst); 1688 if (mtu < ip_rt_min_pmtu) { |
1676 u32 lock = dst_metric(&rth->dst, 1677 RTAX_LOCK); | |
1678 mtu = ip_rt_min_pmtu; | 1689 mtu = ip_rt_min_pmtu; |
1679 lock |= (1 << RTAX_MTU); 1680 dst_metric_set(&rth->dst, RTAX_LOCK, 1681 lock); | 1690 rth->dst.metrics[RTAX_LOCK-1] |= 1691 (1 << RTAX_MTU); |
1682 } | 1692 } |
1683 dst_metric_set(&rth->dst, RTAX_MTU, mtu); | 1693 rth->dst.metrics[RTAX_MTU-1] = mtu; |
1684 dst_set_expires(&rth->dst, 1685 ip_rt_mtu_expires); 1686 } 1687 est_mtu = mtu; 1688 } 1689 } 1690 rcu_read_unlock(); 1691 } 1692 } 1693 return est_mtu ? : new_mtu; 1694} 1695 1696static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) 1697{ 1698 if (dst_mtu(dst) > mtu && mtu >= 68 && 1699 !(dst_metric_locked(dst, RTAX_MTU))) { 1700 if (mtu < ip_rt_min_pmtu) { | 1694 dst_set_expires(&rth->dst, 1695 ip_rt_mtu_expires); 1696 } 1697 est_mtu = mtu; 1698 } 1699 } 1700 rcu_read_unlock(); 1701 } 1702 } 1703 return est_mtu ? : new_mtu; 1704} 1705 1706static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) 1707{ 1708 if (dst_mtu(dst) > mtu && mtu >= 68 && 1709 !(dst_metric_locked(dst, RTAX_MTU))) { 1710 if (mtu < ip_rt_min_pmtu) { |
1701 u32 lock = dst_metric(dst, RTAX_LOCK); | |
1702 mtu = ip_rt_min_pmtu; | 1711 mtu = ip_rt_min_pmtu; |
1703 dst_metric_set(dst, RTAX_LOCK, lock | (1 << RTAX_MTU)); | 1712 dst->metrics[RTAX_LOCK-1] |= (1 << RTAX_MTU); |
1704 } | 1713 } |
1705 dst_metric_set(dst, RTAX_MTU, mtu); | 1714 dst->metrics[RTAX_MTU-1] = mtu; |
1706 dst_set_expires(dst, ip_rt_mtu_expires); 1707 call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); 1708 } 1709} 1710 1711static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) 1712{ 1713 if (rt_is_expired((struct rtable *)dst)) --- 56 unchanged lines hidden (view full) --- 1770 else 1771 src = inet_select_addr(rt->dst.dev, rt->rt_gateway, 1772 RT_SCOPE_UNIVERSE); 1773 rcu_read_unlock(); 1774 } 1775 memcpy(addr, &src, 4); 1776} 1777 | 1715 dst_set_expires(dst, ip_rt_mtu_expires); 1716 call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); 1717 } 1718} 1719 1720static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) 1721{ 1722 if (rt_is_expired((struct rtable *)dst)) --- 56 unchanged lines hidden (view full) --- 1779 else 1780 src = inet_select_addr(rt->dst.dev, rt->rt_gateway, 1781 RT_SCOPE_UNIVERSE); 1782 rcu_read_unlock(); 1783 } 1784 memcpy(addr, &src, 4); 1785} 1786 |
1778#ifdef CONFIG_NET_CLS_ROUTE | 1787#ifdef CONFIG_IP_ROUTE_CLASSID |
1779static void set_class_tag(struct rtable *rt, u32 tag) 1780{ 1781 if (!(rt->dst.tclassid & 0xFFFF)) 1782 rt->dst.tclassid |= tag & 0xFFFF; 1783 if (!(rt->dst.tclassid & 0xFFFF0000)) 1784 rt->dst.tclassid |= tag & 0xFFFF0000; 1785} 1786#endif 1787 | 1788static void set_class_tag(struct rtable *rt, u32 tag) 1789{ 1790 if (!(rt->dst.tclassid & 0xFFFF)) 1791 rt->dst.tclassid |= tag & 0xFFFF; 1792 if (!(rt->dst.tclassid & 0xFFFF0000)) 1793 rt->dst.tclassid |= tag & 0xFFFF0000; 1794} 1795#endif 1796 |
1788static unsigned int ipv4_default_advmss(const struct dst_entry *dst) 1789{ 1790 unsigned int advmss = dst_metric_raw(dst, RTAX_ADVMSS); 1791 1792 if (advmss == 0) { 1793 advmss = max_t(unsigned int, dst->dev->mtu - 40, 1794 ip_rt_min_advmss); 1795 if (advmss > 65535 - 40) 1796 advmss = 65535 - 40; 1797 } 1798 return advmss; 1799} 1800 1801static unsigned int ipv4_default_mtu(const struct dst_entry *dst) 1802{ 1803 unsigned int mtu = dst->dev->mtu; 1804 1805 if (unlikely(dst_metric_locked(dst, RTAX_MTU))) { 1806 const struct rtable *rt = (const struct rtable *) dst; 1807 1808 if (rt->rt_gateway != rt->rt_dst && mtu > 576) 1809 mtu = 576; 1810 } 1811 1812 if (mtu > IP_MAX_MTU) 1813 mtu = IP_MAX_MTU; 1814 1815 return mtu; 1816} 1817 | |
1818static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag) 1819{ | 1797static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag) 1798{ |
1820 struct dst_entry *dst = &rt->dst; | |
1821 struct fib_info *fi = res->fi; 1822 1823 if (fi) { 1824 if (FIB_RES_GW(*res) && 1825 FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) 1826 rt->rt_gateway = FIB_RES_GW(*res); | 1799 struct fib_info *fi = res->fi; 1800 1801 if (fi) { 1802 if (FIB_RES_GW(*res) && 1803 FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) 1804 rt->rt_gateway = FIB_RES_GW(*res); |
1827 dst_import_metrics(dst, fi->fib_metrics); 1828#ifdef CONFIG_NET_CLS_ROUTE 1829 dst->tclassid = FIB_RES_NH(*res).nh_tclassid; | 1805 memcpy(rt->dst.metrics, fi->fib_metrics, 1806 sizeof(rt->dst.metrics)); 1807 if (fi->fib_mtu == 0) { 1808 rt->dst.metrics[RTAX_MTU-1] = rt->dst.dev->mtu; 1809 if (dst_metric_locked(&rt->dst, RTAX_MTU) && 1810 rt->rt_gateway != rt->rt_dst && 1811 rt->dst.dev->mtu > 576) 1812 rt->dst.metrics[RTAX_MTU-1] = 576; 1813 } 1814#ifdef CONFIG_IP_ROUTE_CLASSID 1815 rt->dst.tclassid = FIB_RES_NH(*res).nh_tclassid; |
1830#endif | 1816#endif |
1831 } | 1817 } else 1818 rt->dst.metrics[RTAX_MTU-1]= rt->dst.dev->mtu; |
1832 | 1819 |
1833 if (dst_mtu(dst) > IP_MAX_MTU) 1834 dst_metric_set(dst, RTAX_MTU, IP_MAX_MTU); 1835 if (dst_metric_raw(dst, RTAX_ADVMSS) > 65535 - 40) 1836 dst_metric_set(dst, RTAX_ADVMSS, 65535 - 40); | 1820 if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0) 1821 rt->dst.metrics[RTAX_HOPLIMIT-1] = sysctl_ip_default_ttl; 1822 if (dst_mtu(&rt->dst) > IP_MAX_MTU) 1823 rt->dst.metrics[RTAX_MTU-1] = IP_MAX_MTU; 1824 if (dst_metric(&rt->dst, RTAX_ADVMSS) == 0) 1825 rt->dst.metrics[RTAX_ADVMSS-1] = max_t(unsigned int, rt->dst.dev->mtu - 40, 1826 ip_rt_min_advmss); 1827 if (dst_metric(&rt->dst, RTAX_ADVMSS) > 65535 - 40) 1828 rt->dst.metrics[RTAX_ADVMSS-1] = 65535 - 40; |
1837 | 1829 |
1838#ifdef CONFIG_NET_CLS_ROUTE | 1830#ifdef CONFIG_IP_ROUTE_CLASSID |
1839#ifdef CONFIG_IP_MULTIPLE_TABLES 1840 set_class_tag(rt, fib_rules_tclass(res)); 1841#endif 1842 set_class_tag(rt, itag); 1843#endif 1844 rt->rt_type = res->type; 1845} 1846 --- 39 unchanged lines hidden (view full) --- 1886 if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) 1887 rth->dst.flags |= DST_NOPOLICY; 1888 rth->fl.fl4_dst = daddr; 1889 rth->rt_dst = daddr; 1890 rth->fl.fl4_tos = tos; 1891 rth->fl.mark = skb->mark; 1892 rth->fl.fl4_src = saddr; 1893 rth->rt_src = saddr; | 1831#ifdef CONFIG_IP_MULTIPLE_TABLES 1832 set_class_tag(rt, fib_rules_tclass(res)); 1833#endif 1834 set_class_tag(rt, itag); 1835#endif 1836 rt->rt_type = res->type; 1837} 1838 --- 39 unchanged lines hidden (view full) --- 1878 if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) 1879 rth->dst.flags |= DST_NOPOLICY; 1880 rth->fl.fl4_dst = daddr; 1881 rth->rt_dst = daddr; 1882 rth->fl.fl4_tos = tos; 1883 rth->fl.mark = skb->mark; 1884 rth->fl.fl4_src = saddr; 1885 rth->rt_src = saddr; |
1894#ifdef CONFIG_NET_CLS_ROUTE | 1886#ifdef CONFIG_IP_ROUTE_CLASSID |
1895 rth->dst.tclassid = itag; 1896#endif 1897 rth->rt_iif = 1898 rth->fl.iif = dev->ifindex; 1899 rth->dst.dev = init_net.loopback_dev; 1900 dev_hold(rth->dst.dev); 1901 rth->fl.oif = 0; 1902 rth->rt_gateway = daddr; --- 189 unchanged lines hidden (view full) --- 2092 * called with rcu_read_lock() 2093 */ 2094 2095static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, 2096 u8 tos, struct net_device *dev) 2097{ 2098 struct fib_result res; 2099 struct in_device *in_dev = __in_dev_get_rcu(dev); | 1887 rth->dst.tclassid = itag; 1888#endif 1889 rth->rt_iif = 1890 rth->fl.iif = dev->ifindex; 1891 rth->dst.dev = init_net.loopback_dev; 1892 dev_hold(rth->dst.dev); 1893 rth->fl.oif = 0; 1894 rth->rt_gateway = daddr; --- 189 unchanged lines hidden (view full) --- 2084 * called with rcu_read_lock() 2085 */ 2086 2087static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, 2088 u8 tos, struct net_device *dev) 2089{ 2090 struct fib_result res; 2091 struct in_device *in_dev = __in_dev_get_rcu(dev); |
2100 struct flowi fl = { .fl4_dst = daddr, 2101 .fl4_src = saddr, 2102 .fl4_tos = tos, 2103 .fl4_scope = RT_SCOPE_UNIVERSE, | 2092 struct flowi fl = { .nl_u = { .ip4_u = 2093 { .daddr = daddr, 2094 .saddr = saddr, 2095 .tos = tos, 2096 .scope = RT_SCOPE_UNIVERSE, 2097 } }, |
2104 .mark = skb->mark, 2105 .iif = dev->ifindex }; 2106 unsigned flags = 0; 2107 u32 itag = 0; 2108 struct rtable * rth; 2109 unsigned hash; 2110 __be32 spec_dst; 2111 int err = -EINVAL; --- 91 unchanged lines hidden (view full) --- 2203 if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) 2204 rth->dst.flags |= DST_NOPOLICY; 2205 rth->fl.fl4_dst = daddr; 2206 rth->rt_dst = daddr; 2207 rth->fl.fl4_tos = tos; 2208 rth->fl.mark = skb->mark; 2209 rth->fl.fl4_src = saddr; 2210 rth->rt_src = saddr; | 2098 .mark = skb->mark, 2099 .iif = dev->ifindex }; 2100 unsigned flags = 0; 2101 u32 itag = 0; 2102 struct rtable * rth; 2103 unsigned hash; 2104 __be32 spec_dst; 2105 int err = -EINVAL; --- 91 unchanged lines hidden (view full) --- 2197 if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) 2198 rth->dst.flags |= DST_NOPOLICY; 2199 rth->fl.fl4_dst = daddr; 2200 rth->rt_dst = daddr; 2201 rth->fl.fl4_tos = tos; 2202 rth->fl.mark = skb->mark; 2203 rth->fl.fl4_src = saddr; 2204 rth->rt_src = saddr; |
2211#ifdef CONFIG_NET_CLS_ROUTE | 2205#ifdef CONFIG_IP_ROUTE_CLASSID |
2212 rth->dst.tclassid = itag; 2213#endif 2214 rth->rt_iif = 2215 rth->fl.iif = dev->ifindex; 2216 rth->dst.dev = net->loopback_dev; 2217 dev_hold(rth->dst.dev); 2218 rth->rt_gateway = daddr; 2219 rth->rt_spec_dst= spec_dst; --- 261 unchanged lines hidden (view full) --- 2481 * Major route resolver routine. 2482 * called with rcu_read_lock(); 2483 */ 2484 2485static int ip_route_output_slow(struct net *net, struct rtable **rp, 2486 const struct flowi *oldflp) 2487{ 2488 u32 tos = RT_FL_TOS(oldflp); | 2206 rth->dst.tclassid = itag; 2207#endif 2208 rth->rt_iif = 2209 rth->fl.iif = dev->ifindex; 2210 rth->dst.dev = net->loopback_dev; 2211 dev_hold(rth->dst.dev); 2212 rth->rt_gateway = daddr; 2213 rth->rt_spec_dst= spec_dst; --- 261 unchanged lines hidden (view full) --- 2475 * Major route resolver routine. 2476 * called with rcu_read_lock(); 2477 */ 2478 2479static int ip_route_output_slow(struct net *net, struct rtable **rp, 2480 const struct flowi *oldflp) 2481{ 2482 u32 tos = RT_FL_TOS(oldflp); |
2489 struct flowi fl = { .fl4_dst = oldflp->fl4_dst, 2490 .fl4_src = oldflp->fl4_src, 2491 .fl4_tos = tos & IPTOS_RT_MASK, 2492 .fl4_scope = ((tos & RTO_ONLINK) ? 2493 RT_SCOPE_LINK : RT_SCOPE_UNIVERSE), | 2483 struct flowi fl = { .nl_u = { .ip4_u = 2484 { .daddr = oldflp->fl4_dst, 2485 .saddr = oldflp->fl4_src, 2486 .tos = tos & IPTOS_RT_MASK, 2487 .scope = ((tos & RTO_ONLINK) ? 2488 RT_SCOPE_LINK : 2489 RT_SCOPE_UNIVERSE), 2490 } }, |
2494 .mark = oldflp->mark, 2495 .iif = net->loopback_dev->ifindex, 2496 .oif = oldflp->oif }; 2497 struct fib_result res; 2498 unsigned int flags = 0; 2499 struct net_device *dev_out = NULL; 2500 int err; 2501 --- 55 unchanged lines hidden (view full) --- 2557 2558 if (oldflp->oif) { 2559 dev_out = dev_get_by_index_rcu(net, oldflp->oif); 2560 err = -ENODEV; 2561 if (dev_out == NULL) 2562 goto out; 2563 2564 /* RACE: Check return value of inet_select_addr instead. */ | 2491 .mark = oldflp->mark, 2492 .iif = net->loopback_dev->ifindex, 2493 .oif = oldflp->oif }; 2494 struct fib_result res; 2495 unsigned int flags = 0; 2496 struct net_device *dev_out = NULL; 2497 int err; 2498 --- 55 unchanged lines hidden (view full) --- 2554 2555 if (oldflp->oif) { 2556 dev_out = dev_get_by_index_rcu(net, oldflp->oif); 2557 err = -ENODEV; 2558 if (dev_out == NULL) 2559 goto out; 2560 2561 /* RACE: Check return value of inet_select_addr instead. */ |
2565 if (!(dev_out->flags & IFF_UP) || !__in_dev_get_rcu(dev_out)) { 2566 err = -ENETUNREACH; 2567 goto out; 2568 } | 2562 if (rcu_dereference(dev_out->ip_ptr) == NULL) 2563 goto out; /* Wrong error code */ 2564 |
2569 if (ipv4_is_local_multicast(oldflp->fl4_dst) || 2570 ipv4_is_lbcast(oldflp->fl4_dst)) { 2571 if (!fl.fl4_src) 2572 fl.fl4_src = inet_select_addr(dev_out, 0, 2573 RT_SCOPE_LINK); 2574 goto make_route; 2575 } 2576 if (!fl.fl4_src) { --- 44 unchanged lines hidden (view full) --- 2621 res.type = RTN_UNICAST; 2622 goto make_route; 2623 } 2624 err = -ENETUNREACH; 2625 goto out; 2626 } 2627 2628 if (res.type == RTN_LOCAL) { | 2565 if (ipv4_is_local_multicast(oldflp->fl4_dst) || 2566 ipv4_is_lbcast(oldflp->fl4_dst)) { 2567 if (!fl.fl4_src) 2568 fl.fl4_src = inet_select_addr(dev_out, 0, 2569 RT_SCOPE_LINK); 2570 goto make_route; 2571 } 2572 if (!fl.fl4_src) { --- 44 unchanged lines hidden (view full) --- 2617 res.type = RTN_UNICAST; 2618 goto make_route; 2619 } 2620 err = -ENETUNREACH; 2621 goto out; 2622 } 2623 2624 if (res.type == RTN_LOCAL) { |
2629 if (!fl.fl4_src) { 2630 if (res.fi->fib_prefsrc) 2631 fl.fl4_src = res.fi->fib_prefsrc; 2632 else 2633 fl.fl4_src = fl.fl4_dst; 2634 } | 2625 if (!fl.fl4_src) 2626 fl.fl4_src = fl.fl4_dst; |
2635 dev_out = net->loopback_dev; 2636 fl.oif = dev_out->ifindex; 2637 res.fi = NULL; 2638 flags |= RTCF_LOCAL; 2639 goto make_route; 2640 } 2641 2642#ifdef CONFIG_IP_ROUTE_MULTIPATH --- 85 unchanged lines hidden (view full) --- 2728 2729 if (rt) { 2730 struct dst_entry *new = &rt->dst; 2731 2732 atomic_set(&new->__refcnt, 1); 2733 new->__use = 1; 2734 new->input = dst_discard; 2735 new->output = dst_discard; | 2627 dev_out = net->loopback_dev; 2628 fl.oif = dev_out->ifindex; 2629 res.fi = NULL; 2630 flags |= RTCF_LOCAL; 2631 goto make_route; 2632 } 2633 2634#ifdef CONFIG_IP_ROUTE_MULTIPATH --- 85 unchanged lines hidden (view full) --- 2720 2721 if (rt) { 2722 struct dst_entry *new = &rt->dst; 2723 2724 atomic_set(&new->__refcnt, 1); 2725 new->__use = 1; 2726 new->input = dst_discard; 2727 new->output = dst_discard; |
2736 dst_copy_metrics(new, &ort->dst); | 2728 memcpy(new->metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32)); |
2737 2738 new->dev = ort->dst.dev; 2739 if (new->dev) 2740 dev_hold(new->dev); 2741 2742 rt->fl = ort->fl; 2743 2744 rt->rt_genid = rt_genid(net); --- 78 unchanged lines hidden (view full) --- 2823 NLA_PUT_BE32(skb, RTA_DST, rt->rt_dst); 2824 2825 if (rt->fl.fl4_src) { 2826 r->rtm_src_len = 32; 2827 NLA_PUT_BE32(skb, RTA_SRC, rt->fl.fl4_src); 2828 } 2829 if (rt->dst.dev) 2830 NLA_PUT_U32(skb, RTA_OIF, rt->dst.dev->ifindex); | 2729 2730 new->dev = ort->dst.dev; 2731 if (new->dev) 2732 dev_hold(new->dev); 2733 2734 rt->fl = ort->fl; 2735 2736 rt->rt_genid = rt_genid(net); --- 78 unchanged lines hidden (view full) --- 2815 NLA_PUT_BE32(skb, RTA_DST, rt->rt_dst); 2816 2817 if (rt->fl.fl4_src) { 2818 r->rtm_src_len = 32; 2819 NLA_PUT_BE32(skb, RTA_SRC, rt->fl.fl4_src); 2820 } 2821 if (rt->dst.dev) 2822 NLA_PUT_U32(skb, RTA_OIF, rt->dst.dev->ifindex); |
2831#ifdef CONFIG_NET_CLS_ROUTE | 2823#ifdef CONFIG_IP_ROUTE_CLASSID |
2832 if (rt->dst.tclassid) 2833 NLA_PUT_U32(skb, RTA_FLOW, rt->dst.tclassid); 2834#endif 2835 if (rt_is_input_route(rt)) 2836 NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst); 2837 else if (rt->rt_src != rt->fl.fl4_src) 2838 NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_src); 2839 2840 if (rt->rt_dst != rt->rt_gateway) 2841 NLA_PUT_BE32(skb, RTA_GATEWAY, rt->rt_gateway); 2842 | 2824 if (rt->dst.tclassid) 2825 NLA_PUT_U32(skb, RTA_FLOW, rt->dst.tclassid); 2826#endif 2827 if (rt_is_input_route(rt)) 2828 NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst); 2829 else if (rt->rt_src != rt->fl.fl4_src) 2830 NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_src); 2831 2832 if (rt->rt_dst != rt->rt_gateway) 2833 NLA_PUT_BE32(skb, RTA_GATEWAY, rt->rt_gateway); 2834 |
2843 if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) | 2835 if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0) |
2844 goto nla_put_failure; 2845 2846 if (rt->fl.mark) 2847 NLA_PUT_BE32(skb, RTA_MARK, rt->fl.mark); 2848 2849 error = rt->dst.error; 2850 expires = rt->dst.expires ? rt->dst.expires - jiffies : 0; 2851 if (rt->peer) { --- 95 unchanged lines hidden (view full) --- 2947 err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev); 2948 local_bh_enable(); 2949 2950 rt = skb_rtable(skb); 2951 if (err == 0 && rt->dst.error) 2952 err = -rt->dst.error; 2953 } else { 2954 struct flowi fl = { | 2836 goto nla_put_failure; 2837 2838 if (rt->fl.mark) 2839 NLA_PUT_BE32(skb, RTA_MARK, rt->fl.mark); 2840 2841 error = rt->dst.error; 2842 expires = rt->dst.expires ? rt->dst.expires - jiffies : 0; 2843 if (rt->peer) { --- 95 unchanged lines hidden (view full) --- 2939 err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev); 2940 local_bh_enable(); 2941 2942 rt = skb_rtable(skb); 2943 if (err == 0 && rt->dst.error) 2944 err = -rt->dst.error; 2945 } else { 2946 struct flowi fl = { |
2955 .fl4_dst = dst, 2956 .fl4_src = src, 2957 .fl4_tos = rtm->rtm_tos, | 2947 .nl_u = { 2948 .ip4_u = { 2949 .daddr = dst, 2950 .saddr = src, 2951 .tos = rtm->rtm_tos, 2952 }, 2953 }, |
2958 .oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0, 2959 .mark = mark, 2960 }; 2961 err = ip_route_output_key(net, &rt, &fl); 2962 } 2963 2964 if (err) 2965 goto errout_free; --- 278 unchanged lines hidden (view full) --- 3244 return 0; 3245} 3246 3247static __net_initdata struct pernet_operations rt_genid_ops = { 3248 .init = rt_genid_init, 3249}; 3250 3251 | 2954 .oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0, 2955 .mark = mark, 2956 }; 2957 err = ip_route_output_key(net, &rt, &fl); 2958 } 2959 2960 if (err) 2961 goto errout_free; --- 278 unchanged lines hidden (view full) --- 3240 return 0; 3241} 3242 3243static __net_initdata struct pernet_operations rt_genid_ops = { 3244 .init = rt_genid_init, 3245}; 3246 3247 |
3252#ifdef CONFIG_NET_CLS_ROUTE | 3248#ifdef CONFIG_IP_ROUTE_CLASSID |
3253struct ip_rt_acct __percpu *ip_rt_acct __read_mostly; | 3249struct ip_rt_acct __percpu *ip_rt_acct __read_mostly; |
3254#endif /* CONFIG_NET_CLS_ROUTE */ | 3250#endif /* CONFIG_IP_ROUTE_CLASSID */ |
3255 3256static __initdata unsigned long rhash_entries; 3257static int __init set_rhash_entries(char *str) 3258{ 3259 if (!str) 3260 return 0; 3261 rhash_entries = simple_strtoul(str, &str, 0); 3262 return 1; 3263} 3264__setup("rhash_entries=", set_rhash_entries); 3265 3266int __init ip_rt_init(void) 3267{ 3268 int rc = 0; 3269 | 3251 3252static __initdata unsigned long rhash_entries; 3253static int __init set_rhash_entries(char *str) 3254{ 3255 if (!str) 3256 return 0; 3257 rhash_entries = simple_strtoul(str, &str, 0); 3258 return 1; 3259} 3260__setup("rhash_entries=", set_rhash_entries); 3261 3262int __init ip_rt_init(void) 3263{ 3264 int rc = 0; 3265 |
3270#ifdef CONFIG_NET_CLS_ROUTE | 3266#ifdef CONFIG_IP_ROUTE_CLASSID |
3271 ip_rt_acct = __alloc_percpu(256 * sizeof(struct ip_rt_acct), __alignof__(struct ip_rt_acct)); 3272 if (!ip_rt_acct) 3273 panic("IP: failed to allocate ip_rt_acct\n"); 3274#endif 3275 3276 ipv4_dst_ops.kmem_cachep = 3277 kmem_cache_create("ip_dst_cache", sizeof(struct rtable), 0, 3278 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); --- 61 unchanged lines hidden --- | 3267 ip_rt_acct = __alloc_percpu(256 * sizeof(struct ip_rt_acct), __alignof__(struct ip_rt_acct)); 3268 if (!ip_rt_acct) 3269 panic("IP: failed to allocate ip_rt_acct\n"); 3270#endif 3271 3272 ipv4_dst_ops.kmem_cachep = 3273 kmem_cache_create("ip_dst_cache", sizeof(struct rtable), 0, 3274 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); --- 61 unchanged lines hidden --- |