diff options
-rw-r--r-- | include/net/dst.h | 6 | ||||
-rw-r--r-- | include/net/ip6_fib.h | 42 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 9 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 9 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 3 | ||||
-rw-r--r-- | net/ipv6/route.c | 71 |
6 files changed, 99 insertions, 41 deletions
diff --git a/include/net/dst.h b/include/net/dst.h index 59c5d18cc385..ff4da42fcfc6 100644 --- a/include/net/dst.h +++ b/include/net/dst.h | |||
@@ -36,7 +36,11 @@ struct dst_entry { | |||
36 | struct net_device *dev; | 36 | struct net_device *dev; |
37 | struct dst_ops *ops; | 37 | struct dst_ops *ops; |
38 | unsigned long _metrics; | 38 | unsigned long _metrics; |
39 | unsigned long expires; | 39 | union { |
40 | unsigned long expires; | ||
41 | /* point to where the dst_entry copied from */ | ||
42 | struct dst_entry *from; | ||
43 | }; | ||
40 | struct dst_entry *path; | 44 | struct dst_entry *path; |
41 | struct neighbour __rcu *_neighbour; | 45 | struct neighbour __rcu *_neighbour; |
42 | #ifdef CONFIG_XFRM | 46 | #ifdef CONFIG_XFRM |
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index b26bb8101981..c64778fd5e13 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h | |||
@@ -123,6 +123,48 @@ static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst) | |||
123 | return ((struct rt6_info *)dst)->rt6i_idev; | 123 | return ((struct rt6_info *)dst)->rt6i_idev; |
124 | } | 124 | } |
125 | 125 | ||
126 | static inline void rt6_clean_expires(struct rt6_info *rt) | ||
127 | { | ||
128 | if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) | ||
129 | dst_release(rt->dst.from); | ||
130 | |||
131 | rt->rt6i_flags &= ~RTF_EXPIRES; | ||
132 | rt->dst.expires = 0; | ||
133 | } | ||
134 | |||
135 | static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires) | ||
136 | { | ||
137 | if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) | ||
138 | dst_release(rt->dst.from); | ||
139 | |||
140 | rt->rt6i_flags |= RTF_EXPIRES; | ||
141 | rt->dst.expires = expires; | ||
142 | } | ||
143 | |||
144 | static inline void rt6_update_expires(struct rt6_info *rt, int timeout) | ||
145 | { | ||
146 | if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) | ||
147 | dst_release(rt->dst.from); | ||
148 | |||
149 | dst_set_expires(&rt->dst, timeout); | ||
150 | rt->rt6i_flags |= RTF_EXPIRES; | ||
151 | } | ||
152 | |||
153 | static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from) | ||
154 | { | ||
155 | struct dst_entry *new = (struct dst_entry *) from; | ||
156 | |||
157 | if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) { | ||
158 | if (new == rt->dst.from) | ||
159 | return; | ||
160 | dst_release(rt->dst.from); | ||
161 | } | ||
162 | |||
163 | rt->rt6i_flags &= ~RTF_EXPIRES; | ||
164 | rt->dst.from = new; | ||
165 | dst_hold(new); | ||
166 | } | ||
167 | |||
126 | struct fib6_walker_t { | 168 | struct fib6_walker_t { |
127 | struct list_head lh; | 169 | struct list_head lh; |
128 | struct fib6_node *root, *node; | 170 | struct fib6_node *root, *node; |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 6a3bb6077e19..7d5cb975cc6f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -803,8 +803,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
803 | ip6_del_rt(rt); | 803 | ip6_del_rt(rt); |
804 | rt = NULL; | 804 | rt = NULL; |
805 | } else if (!(rt->rt6i_flags & RTF_EXPIRES)) { | 805 | } else if (!(rt->rt6i_flags & RTF_EXPIRES)) { |
806 | rt->dst.expires = expires; | 806 | rt6_set_expires(rt, expires); |
807 | rt->rt6i_flags |= RTF_EXPIRES; | ||
808 | } | 807 | } |
809 | } | 808 | } |
810 | dst_release(&rt->dst); | 809 | dst_release(&rt->dst); |
@@ -1887,11 +1886,9 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) | |||
1887 | rt = NULL; | 1886 | rt = NULL; |
1888 | } else if (addrconf_finite_timeout(rt_expires)) { | 1887 | } else if (addrconf_finite_timeout(rt_expires)) { |
1889 | /* not infinity */ | 1888 | /* not infinity */ |
1890 | rt->dst.expires = jiffies + rt_expires; | 1889 | rt6_set_expires(rt, jiffies + rt_expires); |
1891 | rt->rt6i_flags |= RTF_EXPIRES; | ||
1892 | } else { | 1890 | } else { |
1893 | rt->rt6i_flags &= ~RTF_EXPIRES; | 1891 | rt6_clean_expires(rt); |
1894 | rt->dst.expires = 0; | ||
1895 | } | 1892 | } |
1896 | } else if (valid_lft) { | 1893 | } else if (valid_lft) { |
1897 | clock_t expires = 0; | 1894 | clock_t expires = 0; |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 5b27fbcae346..93717435013e 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -673,11 +673,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
673 | &rt->rt6i_gateway)) { | 673 | &rt->rt6i_gateway)) { |
674 | if (!(iter->rt6i_flags & RTF_EXPIRES)) | 674 | if (!(iter->rt6i_flags & RTF_EXPIRES)) |
675 | return -EEXIST; | 675 | return -EEXIST; |
676 | iter->dst.expires = rt->dst.expires; | 676 | if (!(rt->rt6i_flags & RTF_EXPIRES)) |
677 | if (!(rt->rt6i_flags & RTF_EXPIRES)) { | 677 | rt6_clean_expires(iter); |
678 | iter->rt6i_flags &= ~RTF_EXPIRES; | 678 | else |
679 | iter->dst.expires = 0; | 679 | rt6_set_expires(iter, rt->dst.expires); |
680 | } | ||
681 | return -EEXIST; | 680 | return -EEXIST; |
682 | } | 681 | } |
683 | } | 682 | } |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3dcdb81ec3e8..176b469322ac 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1264,8 +1264,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1264 | } | 1264 | } |
1265 | 1265 | ||
1266 | if (rt) | 1266 | if (rt) |
1267 | rt->dst.expires = jiffies + (HZ * lifetime); | 1267 | rt6_set_expires(rt, jiffies + (HZ * lifetime)); |
1268 | |||
1269 | if (ra_msg->icmph.icmp6_hop_limit) { | 1268 | if (ra_msg->icmph.icmp6_hop_limit) { |
1270 | in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; | 1269 | in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; |
1271 | if (rt) | 1270 | if (rt) |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 3992e26a6039..bc4888d902b2 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -62,7 +62,7 @@ | |||
62 | #include <linux/sysctl.h> | 62 | #include <linux/sysctl.h> |
63 | #endif | 63 | #endif |
64 | 64 | ||
65 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | 65 | static struct rt6_info *ip6_rt_copy(struct rt6_info *ort, |
66 | const struct in6_addr *dest); | 66 | const struct in6_addr *dest); |
67 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); | 67 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); |
68 | static unsigned int ip6_default_advmss(const struct dst_entry *dst); | 68 | static unsigned int ip6_default_advmss(const struct dst_entry *dst); |
@@ -285,6 +285,10 @@ static void ip6_dst_destroy(struct dst_entry *dst) | |||
285 | rt->rt6i_idev = NULL; | 285 | rt->rt6i_idev = NULL; |
286 | in6_dev_put(idev); | 286 | in6_dev_put(idev); |
287 | } | 287 | } |
288 | |||
289 | if (!(rt->rt6i_flags & RTF_EXPIRES) && dst->from) | ||
290 | dst_release(dst->from); | ||
291 | |||
288 | if (peer) { | 292 | if (peer) { |
289 | rt->rt6i_peer = NULL; | 293 | rt->rt6i_peer = NULL; |
290 | inet_putpeer(peer); | 294 | inet_putpeer(peer); |
@@ -329,8 +333,17 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
329 | 333 | ||
330 | static __inline__ int rt6_check_expired(const struct rt6_info *rt) | 334 | static __inline__ int rt6_check_expired(const struct rt6_info *rt) |
331 | { | 335 | { |
332 | return (rt->rt6i_flags & RTF_EXPIRES) && | 336 | struct rt6_info *ort = NULL; |
333 | time_after(jiffies, rt->dst.expires); | 337 | |
338 | if (rt->rt6i_flags & RTF_EXPIRES) { | ||
339 | if (time_after(jiffies, rt->dst.expires)) | ||
340 | return 1; | ||
341 | } else if (rt->dst.from) { | ||
342 | ort = (struct rt6_info *) rt->dst.from; | ||
343 | return (ort->rt6i_flags & RTF_EXPIRES) && | ||
344 | time_after(jiffies, ort->dst.expires); | ||
345 | } | ||
346 | return 0; | ||
334 | } | 347 | } |
335 | 348 | ||
336 | static inline int rt6_need_strict(const struct in6_addr *daddr) | 349 | static inline int rt6_need_strict(const struct in6_addr *daddr) |
@@ -620,12 +633,11 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
620 | (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); | 633 | (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); |
621 | 634 | ||
622 | if (rt) { | 635 | if (rt) { |
623 | if (!addrconf_finite_timeout(lifetime)) { | 636 | if (!addrconf_finite_timeout(lifetime)) |
624 | rt->rt6i_flags &= ~RTF_EXPIRES; | 637 | rt6_clean_expires(rt); |
625 | } else { | 638 | else |
626 | rt->dst.expires = jiffies + HZ * lifetime; | 639 | rt6_set_expires(rt, jiffies + HZ * lifetime); |
627 | rt->rt6i_flags |= RTF_EXPIRES; | 640 | |
628 | } | ||
629 | dst_release(&rt->dst); | 641 | dst_release(&rt->dst); |
630 | } | 642 | } |
631 | return 0; | 643 | return 0; |
@@ -730,7 +742,7 @@ int ip6_ins_rt(struct rt6_info *rt) | |||
730 | return __ip6_ins_rt(rt, &info); | 742 | return __ip6_ins_rt(rt, &info); |
731 | } | 743 | } |
732 | 744 | ||
733 | static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, | 745 | static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, |
734 | const struct in6_addr *daddr, | 746 | const struct in6_addr *daddr, |
735 | const struct in6_addr *saddr) | 747 | const struct in6_addr *saddr) |
736 | { | 748 | { |
@@ -954,10 +966,10 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori | |||
954 | rt->rt6i_idev = ort->rt6i_idev; | 966 | rt->rt6i_idev = ort->rt6i_idev; |
955 | if (rt->rt6i_idev) | 967 | if (rt->rt6i_idev) |
956 | in6_dev_hold(rt->rt6i_idev); | 968 | in6_dev_hold(rt->rt6i_idev); |
957 | rt->dst.expires = 0; | ||
958 | 969 | ||
959 | rt->rt6i_gateway = ort->rt6i_gateway; | 970 | rt->rt6i_gateway = ort->rt6i_gateway; |
960 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; | 971 | rt->rt6i_flags = ort->rt6i_flags; |
972 | rt6_clean_expires(rt); | ||
961 | rt->rt6i_metric = 0; | 973 | rt->rt6i_metric = 0; |
962 | 974 | ||
963 | memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); | 975 | memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); |
@@ -1019,10 +1031,9 @@ static void ip6_link_failure(struct sk_buff *skb) | |||
1019 | 1031 | ||
1020 | rt = (struct rt6_info *) skb_dst(skb); | 1032 | rt = (struct rt6_info *) skb_dst(skb); |
1021 | if (rt) { | 1033 | if (rt) { |
1022 | if (rt->rt6i_flags & RTF_CACHE) { | 1034 | if (rt->rt6i_flags & RTF_CACHE) |
1023 | dst_set_expires(&rt->dst, 0); | 1035 | rt6_update_expires(rt, 0); |
1024 | rt->rt6i_flags |= RTF_EXPIRES; | 1036 | else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) |
1025 | } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) | ||
1026 | rt->rt6i_node->fn_sernum = -1; | 1037 | rt->rt6i_node->fn_sernum = -1; |
1027 | } | 1038 | } |
1028 | } | 1039 | } |
@@ -1289,9 +1300,12 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1289 | } | 1300 | } |
1290 | 1301 | ||
1291 | rt->dst.obsolete = -1; | 1302 | rt->dst.obsolete = -1; |
1292 | rt->dst.expires = (cfg->fc_flags & RTF_EXPIRES) ? | 1303 | |
1293 | jiffies + clock_t_to_jiffies(cfg->fc_expires) : | 1304 | if (cfg->fc_flags & RTF_EXPIRES) |
1294 | 0; | 1305 | rt6_set_expires(rt, jiffies + |
1306 | clock_t_to_jiffies(cfg->fc_expires)); | ||
1307 | else | ||
1308 | rt6_clean_expires(rt); | ||
1295 | 1309 | ||
1296 | if (cfg->fc_protocol == RTPROT_UNSPEC) | 1310 | if (cfg->fc_protocol == RTPROT_UNSPEC) |
1297 | cfg->fc_protocol = RTPROT_BOOT; | 1311 | cfg->fc_protocol = RTPROT_BOOT; |
@@ -1736,8 +1750,8 @@ again: | |||
1736 | features |= RTAX_FEATURE_ALLFRAG; | 1750 | features |= RTAX_FEATURE_ALLFRAG; |
1737 | dst_metric_set(&rt->dst, RTAX_FEATURES, features); | 1751 | dst_metric_set(&rt->dst, RTAX_FEATURES, features); |
1738 | } | 1752 | } |
1739 | dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); | 1753 | rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires); |
1740 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; | 1754 | rt->rt6i_flags |= RTF_MODIFIED; |
1741 | goto out; | 1755 | goto out; |
1742 | } | 1756 | } |
1743 | 1757 | ||
@@ -1765,9 +1779,8 @@ again: | |||
1765 | * which is 10 mins. After 10 mins the decreased pmtu is expired | 1779 | * which is 10 mins. After 10 mins the decreased pmtu is expired |
1766 | * and detecting PMTU increase will be automatically happened. | 1780 | * and detecting PMTU increase will be automatically happened. |
1767 | */ | 1781 | */ |
1768 | dst_set_expires(&nrt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); | 1782 | rt6_update_expires(nrt, net->ipv6.sysctl.ip6_rt_mtu_expires); |
1769 | nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; | 1783 | nrt->rt6i_flags |= RTF_DYNAMIC; |
1770 | |||
1771 | ip6_ins_rt(nrt); | 1784 | ip6_ins_rt(nrt); |
1772 | } | 1785 | } |
1773 | out: | 1786 | out: |
@@ -1799,7 +1812,7 @@ void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *sad | |||
1799 | * Misc support functions | 1812 | * Misc support functions |
1800 | */ | 1813 | */ |
1801 | 1814 | ||
1802 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | 1815 | static struct rt6_info *ip6_rt_copy(struct rt6_info *ort, |
1803 | const struct in6_addr *dest) | 1816 | const struct in6_addr *dest) |
1804 | { | 1817 | { |
1805 | struct net *net = dev_net(ort->dst.dev); | 1818 | struct net *net = dev_net(ort->dst.dev); |
@@ -1819,10 +1832,14 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | |||
1819 | if (rt->rt6i_idev) | 1832 | if (rt->rt6i_idev) |
1820 | in6_dev_hold(rt->rt6i_idev); | 1833 | in6_dev_hold(rt->rt6i_idev); |
1821 | rt->dst.lastuse = jiffies; | 1834 | rt->dst.lastuse = jiffies; |
1822 | rt->dst.expires = 0; | ||
1823 | 1835 | ||
1824 | rt->rt6i_gateway = ort->rt6i_gateway; | 1836 | rt->rt6i_gateway = ort->rt6i_gateway; |
1825 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; | 1837 | rt->rt6i_flags = ort->rt6i_flags; |
1838 | if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == | ||
1839 | (RTF_DEFAULT | RTF_ADDRCONF)) | ||
1840 | rt6_set_from(rt, ort); | ||
1841 | else | ||
1842 | rt6_clean_expires(rt); | ||
1826 | rt->rt6i_metric = 0; | 1843 | rt->rt6i_metric = 0; |
1827 | 1844 | ||
1828 | #ifdef CONFIG_IPV6_SUBTREES | 1845 | #ifdef CONFIG_IPV6_SUBTREES |