aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c54
1 files changed, 33 insertions, 21 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 28205e5bfa9b..cd76b3cb7092 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -131,8 +131,8 @@ static int ip_rt_min_advmss __read_mostly = 256;
131static int ip_rt_secret_interval __read_mostly = 10 * 60 * HZ; 131static int ip_rt_secret_interval __read_mostly = 10 * 60 * HZ;
132static int rt_chain_length_max __read_mostly = 20; 132static int rt_chain_length_max __read_mostly = 20;
133 133
134static void rt_worker_func(struct work_struct *work); 134static struct delayed_work expires_work;
135static DECLARE_DELAYED_WORK(expires_work, rt_worker_func); 135static unsigned long expires_ljiffies;
136 136
137/* 137/*
138 * Interface to generic destination cache. 138 * Interface to generic destination cache.
@@ -787,9 +787,12 @@ static void rt_check_expire(void)
787 struct rtable *rth, *aux, **rthp; 787 struct rtable *rth, *aux, **rthp;
788 unsigned long samples = 0; 788 unsigned long samples = 0;
789 unsigned long sum = 0, sum2 = 0; 789 unsigned long sum = 0, sum2 = 0;
790 unsigned long delta;
790 u64 mult; 791 u64 mult;
791 792
792 mult = ((u64)ip_rt_gc_interval) << rt_hash_log; 793 delta = jiffies - expires_ljiffies;
794 expires_ljiffies = jiffies;
795 mult = ((u64)delta) << rt_hash_log;
793 if (ip_rt_gc_timeout > 1) 796 if (ip_rt_gc_timeout > 1)
794 do_div(mult, ip_rt_gc_timeout); 797 do_div(mult, ip_rt_gc_timeout);
795 goal = (unsigned int)mult; 798 goal = (unsigned int)mult;
@@ -1064,7 +1067,8 @@ work_done:
1064out: return 0; 1067out: return 0;
1065} 1068}
1066 1069
1067static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp) 1070static int rt_intern_hash(unsigned hash, struct rtable *rt,
1071 struct rtable **rp, struct sk_buff *skb)
1068{ 1072{
1069 struct rtable *rth, **rthp; 1073 struct rtable *rth, **rthp;
1070 unsigned long now; 1074 unsigned long now;
@@ -1114,7 +1118,10 @@ restart:
1114 spin_unlock_bh(rt_hash_lock_addr(hash)); 1118 spin_unlock_bh(rt_hash_lock_addr(hash));
1115 1119
1116 rt_drop(rt); 1120 rt_drop(rt);
1117 *rp = rth; 1121 if (rp)
1122 *rp = rth;
1123 else
1124 skb_dst_set(skb, &rth->u.dst);
1118 return 0; 1125 return 0;
1119 } 1126 }
1120 1127
@@ -1210,7 +1217,10 @@ restart:
1210 rcu_assign_pointer(rt_hash_table[hash].chain, rt); 1217 rcu_assign_pointer(rt_hash_table[hash].chain, rt);
1211 1218
1212 spin_unlock_bh(rt_hash_lock_addr(hash)); 1219 spin_unlock_bh(rt_hash_lock_addr(hash));
1213 *rp = rt; 1220 if (rp)
1221 *rp = rt;
1222 else
1223 skb_dst_set(skb, &rt->u.dst);
1214 return 0; 1224 return 0;
1215} 1225}
1216 1226
@@ -1407,7 +1417,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1407 &netevent); 1417 &netevent);
1408 1418
1409 rt_del(hash, rth); 1419 rt_del(hash, rth);
1410 if (!rt_intern_hash(hash, rt, &rt)) 1420 if (!rt_intern_hash(hash, rt, &rt, NULL))
1411 ip_rt_put(rt); 1421 ip_rt_put(rt);
1412 goto do_next; 1422 goto do_next;
1413 } 1423 }
@@ -1473,7 +1483,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
1473 1483
1474void ip_rt_send_redirect(struct sk_buff *skb) 1484void ip_rt_send_redirect(struct sk_buff *skb)
1475{ 1485{
1476 struct rtable *rt = skb->rtable; 1486 struct rtable *rt = skb_rtable(skb);
1477 struct in_device *in_dev = in_dev_get(rt->u.dst.dev); 1487 struct in_device *in_dev = in_dev_get(rt->u.dst.dev);
1478 1488
1479 if (!in_dev) 1489 if (!in_dev)
@@ -1521,7 +1531,7 @@ out:
1521 1531
1522static int ip_error(struct sk_buff *skb) 1532static int ip_error(struct sk_buff *skb)
1523{ 1533{
1524 struct rtable *rt = skb->rtable; 1534 struct rtable *rt = skb_rtable(skb);
1525 unsigned long now; 1535 unsigned long now;
1526 int code; 1536 int code;
1527 1537
@@ -1698,7 +1708,7 @@ static void ipv4_link_failure(struct sk_buff *skb)
1698 1708
1699 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); 1709 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
1700 1710
1701 rt = skb->rtable; 1711 rt = skb_rtable(skb);
1702 if (rt) 1712 if (rt)
1703 dst_set_expires(&rt->u.dst, 0); 1713 dst_set_expires(&rt->u.dst, 0);
1704} 1714}
@@ -1858,7 +1868,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1858 1868
1859 in_dev_put(in_dev); 1869 in_dev_put(in_dev);
1860 hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); 1870 hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev)));
1861 return rt_intern_hash(hash, rth, &skb->rtable); 1871 return rt_intern_hash(hash, rth, NULL, skb);
1862 1872
1863e_nobufs: 1873e_nobufs:
1864 in_dev_put(in_dev); 1874 in_dev_put(in_dev);
@@ -2019,7 +2029,7 @@ static int ip_mkroute_input(struct sk_buff *skb,
2019 /* put it into the cache */ 2029 /* put it into the cache */
2020 hash = rt_hash(daddr, saddr, fl->iif, 2030 hash = rt_hash(daddr, saddr, fl->iif,
2021 rt_genid(dev_net(rth->u.dst.dev))); 2031 rt_genid(dev_net(rth->u.dst.dev)));
2022 return rt_intern_hash(hash, rth, &skb->rtable); 2032 return rt_intern_hash(hash, rth, NULL, skb);
2023} 2033}
2024 2034
2025/* 2035/*
@@ -2175,7 +2185,7 @@ local_input:
2175 } 2185 }
2176 rth->rt_type = res.type; 2186 rth->rt_type = res.type;
2177 hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net)); 2187 hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net));
2178 err = rt_intern_hash(hash, rth, &skb->rtable); 2188 err = rt_intern_hash(hash, rth, NULL, skb);
2179 goto done; 2189 goto done;
2180 2190
2181no_route: 2191no_route:
@@ -2244,7 +2254,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
2244 dst_use(&rth->u.dst, jiffies); 2254 dst_use(&rth->u.dst, jiffies);
2245 RT_CACHE_STAT_INC(in_hit); 2255 RT_CACHE_STAT_INC(in_hit);
2246 rcu_read_unlock(); 2256 rcu_read_unlock();
2247 skb->rtable = rth; 2257 skb_dst_set(skb, &rth->u.dst);
2248 return 0; 2258 return 0;
2249 } 2259 }
2250 RT_CACHE_STAT_INC(in_hlist_search); 2260 RT_CACHE_STAT_INC(in_hlist_search);
@@ -2420,7 +2430,7 @@ static int ip_mkroute_output(struct rtable **rp,
2420 if (err == 0) { 2430 if (err == 0) {
2421 hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif, 2431 hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif,
2422 rt_genid(dev_net(dev_out))); 2432 rt_genid(dev_net(dev_out)));
2423 err = rt_intern_hash(hash, rth, rp); 2433 err = rt_intern_hash(hash, rth, rp, NULL);
2424 } 2434 }
2425 2435
2426 return err; 2436 return err;
@@ -2763,7 +2773,7 @@ static int rt_fill_info(struct net *net,
2763 struct sk_buff *skb, u32 pid, u32 seq, int event, 2773 struct sk_buff *skb, u32 pid, u32 seq, int event,
2764 int nowait, unsigned int flags) 2774 int nowait, unsigned int flags)
2765{ 2775{
2766 struct rtable *rt = skb->rtable; 2776 struct rtable *rt = skb_rtable(skb);
2767 struct rtmsg *r; 2777 struct rtmsg *r;
2768 struct nlmsghdr *nlh; 2778 struct nlmsghdr *nlh;
2769 long expires; 2779 long expires;
@@ -2907,7 +2917,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
2907 err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev); 2917 err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);
2908 local_bh_enable(); 2918 local_bh_enable();
2909 2919
2910 rt = skb->rtable; 2920 rt = skb_rtable(skb);
2911 if (err == 0 && rt->u.dst.error) 2921 if (err == 0 && rt->u.dst.error)
2912 err = -rt->u.dst.error; 2922 err = -rt->u.dst.error;
2913 } else { 2923 } else {
@@ -2927,7 +2937,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
2927 if (err) 2937 if (err)
2928 goto errout_free; 2938 goto errout_free;
2929 2939
2930 skb->rtable = rt; 2940 skb_dst_set(skb, &rt->u.dst);
2931 if (rtm->rtm_flags & RTM_F_NOTIFY) 2941 if (rtm->rtm_flags & RTM_F_NOTIFY)
2932 rt->rt_flags |= RTCF_NOTIFY; 2942 rt->rt_flags |= RTCF_NOTIFY;
2933 2943
@@ -2968,15 +2978,15 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
2968 continue; 2978 continue;
2969 if (rt_is_expired(rt)) 2979 if (rt_is_expired(rt))
2970 continue; 2980 continue;
2971 skb->dst = dst_clone(&rt->u.dst); 2981 skb_dst_set(skb, dst_clone(&rt->u.dst));
2972 if (rt_fill_info(net, skb, NETLINK_CB(cb->skb).pid, 2982 if (rt_fill_info(net, skb, NETLINK_CB(cb->skb).pid,
2973 cb->nlh->nlmsg_seq, RTM_NEWROUTE, 2983 cb->nlh->nlmsg_seq, RTM_NEWROUTE,
2974 1, NLM_F_MULTI) <= 0) { 2984 1, NLM_F_MULTI) <= 0) {
2975 dst_release(xchg(&skb->dst, NULL)); 2985 skb_dst_drop(skb);
2976 rcu_read_unlock_bh(); 2986 rcu_read_unlock_bh();
2977 goto done; 2987 goto done;
2978 } 2988 }
2979 dst_release(xchg(&skb->dst, NULL)); 2989 skb_dst_drop(skb);
2980 } 2990 }
2981 rcu_read_unlock_bh(); 2991 rcu_read_unlock_bh();
2982 } 2992 }
@@ -3390,6 +3400,8 @@ int __init ip_rt_init(void)
3390 /* All the timers, started at system startup tend 3400 /* All the timers, started at system startup tend
3391 to synchronize. Perturb it a bit. 3401 to synchronize. Perturb it a bit.
3392 */ 3402 */
3403 INIT_DELAYED_WORK_DEFERRABLE(&expires_work, rt_worker_func);
3404 expires_ljiffies = jiffies;
3393 schedule_delayed_work(&expires_work, 3405 schedule_delayed_work(&expires_work,
3394 net_random() % ip_rt_gc_interval + ip_rt_gc_interval); 3406 net_random() % ip_rt_gc_interval + ip_rt_gc_interval);
3395 3407