Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipv4: Restart rt_intern_hash after emergency rebuild (v2)

The the rebuild changes the genid which in turn is used at
the hash calculation. Thus if we don't restart and go on with
inserting the rt will happen in wrong chain.

(Fixed Neil's comment about the index passed into the rt_intern_hash)

Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Reviewed-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Pavel Emelyanov and committed by
David S. Miller
6a2bad70 b35ecb5d

+11 -6
+11 -6
net/ipv4/route.c
··· 1097 1097 } 1098 1098 1099 1099 static int rt_intern_hash(unsigned hash, struct rtable *rt, 1100 - struct rtable **rp, struct sk_buff *skb) 1100 + struct rtable **rp, struct sk_buff *skb, int ifindex) 1101 1101 { 1102 1102 struct rtable *rth, **rthp; 1103 1103 unsigned long now; ··· 1217 1217 rt->u.dst.dev->name, num); 1218 1218 } 1219 1219 rt_emergency_hash_rebuild(net); 1220 + spin_unlock_bh(rt_hash_lock_addr(hash)); 1221 + 1222 + hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src, 1223 + ifindex, rt_genid(net)); 1224 + goto restart; 1220 1225 } 1221 1226 } 1222 1227 ··· 1482 1477 &netevent); 1483 1478 1484 1479 rt_del(hash, rth); 1485 - if (!rt_intern_hash(hash, rt, &rt, NULL)) 1480 + if (!rt_intern_hash(hash, rt, &rt, NULL, rt->fl.oif)) 1486 1481 ip_rt_put(rt); 1487 1482 goto do_next; 1488 1483 } ··· 1936 1931 1937 1932 in_dev_put(in_dev); 1938 1933 hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); 1939 - return rt_intern_hash(hash, rth, NULL, skb); 1934 + return rt_intern_hash(hash, rth, NULL, skb, dev->ifindex); 1940 1935 1941 1936 e_nobufs: 1942 1937 in_dev_put(in_dev); ··· 2103 2098 /* put it into the cache */ 2104 2099 hash = rt_hash(daddr, saddr, fl->iif, 2105 2100 rt_genid(dev_net(rth->u.dst.dev))); 2106 - return rt_intern_hash(hash, rth, NULL, skb); 2101 + return rt_intern_hash(hash, rth, NULL, skb, fl->iif); 2107 2102 } 2108 2103 2109 2104 /* ··· 2260 2255 } 2261 2256 rth->rt_type = res.type; 2262 2257 hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net)); 2263 - err = rt_intern_hash(hash, rth, NULL, skb); 2258 + err = rt_intern_hash(hash, rth, NULL, skb, fl.iif); 2264 2259 goto done; 2265 2260 2266 2261 no_route: ··· 2507 2502 if (err == 0) { 2508 2503 hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif, 2509 2504 rt_genid(dev_net(dev_out))); 2510 - err = rt_intern_hash(hash, rth, rp, NULL); 2505 + err = rt_intern_hash(hash, rth, rp, NULL, oldflp->oif); 2511 2506 } 2512 2507 2513 2508 return err;