diff options
Diffstat (limited to 'net/ipv4/fib_frontend.c')
-rw-r--r-- | net/ipv4/fib_frontend.c | 192 |
1 files changed, 103 insertions, 89 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 7d02a9f999fa..36e27c2107de 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -147,35 +147,43 @@ static void fib_flush(struct net *net) | |||
147 | rt_cache_flush(net, -1); | 147 | rt_cache_flush(net, -1); |
148 | } | 148 | } |
149 | 149 | ||
150 | /* | 150 | /** |
151 | * Find the first device with a given source address. | 151 | * __ip_dev_find - find the first device with a given source address. |
152 | * @net: the net namespace | ||
153 | * @addr: the source address | ||
154 | * @devref: if true, take a reference on the found device | ||
155 | * | ||
156 | * If a caller uses devref=false, it should be protected by RCU, or RTNL | ||
152 | */ | 157 | */ |
153 | 158 | struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref) | |
154 | struct net_device * ip_dev_find(struct net *net, __be32 addr) | ||
155 | { | 159 | { |
156 | struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } }; | 160 | struct flowi fl = { |
157 | struct fib_result res; | 161 | .nl_u = { |
162 | .ip4_u = { | ||
163 | .daddr = addr | ||
164 | } | ||
165 | }, | ||
166 | .flags = FLOWI_FLAG_MATCH_ANY_IIF | ||
167 | }; | ||
168 | struct fib_result res = { 0 }; | ||
158 | struct net_device *dev = NULL; | 169 | struct net_device *dev = NULL; |
159 | struct fib_table *local_table; | ||
160 | 170 | ||
161 | #ifdef CONFIG_IP_MULTIPLE_TABLES | 171 | rcu_read_lock(); |
162 | res.r = NULL; | 172 | if (fib_lookup(net, &fl, &res)) { |
163 | #endif | 173 | rcu_read_unlock(); |
164 | |||
165 | local_table = fib_get_table(net, RT_TABLE_LOCAL); | ||
166 | if (!local_table || fib_table_lookup(local_table, &fl, &res)) | ||
167 | return NULL; | 174 | return NULL; |
175 | } | ||
168 | if (res.type != RTN_LOCAL) | 176 | if (res.type != RTN_LOCAL) |
169 | goto out; | 177 | goto out; |
170 | dev = FIB_RES_DEV(res); | 178 | dev = FIB_RES_DEV(res); |
171 | 179 | ||
172 | if (dev) | 180 | if (dev && devref) |
173 | dev_hold(dev); | 181 | dev_hold(dev); |
174 | out: | 182 | out: |
175 | fib_res_put(&res); | 183 | rcu_read_unlock(); |
176 | return dev; | 184 | return dev; |
177 | } | 185 | } |
178 | EXPORT_SYMBOL(ip_dev_find); | 186 | EXPORT_SYMBOL(__ip_dev_find); |
179 | 187 | ||
180 | /* | 188 | /* |
181 | * Find address type as if only "dev" was present in the system. If | 189 | * Find address type as if only "dev" was present in the system. If |
@@ -202,11 +210,12 @@ static inline unsigned __inet_dev_addr_type(struct net *net, | |||
202 | local_table = fib_get_table(net, RT_TABLE_LOCAL); | 210 | local_table = fib_get_table(net, RT_TABLE_LOCAL); |
203 | if (local_table) { | 211 | if (local_table) { |
204 | ret = RTN_UNICAST; | 212 | ret = RTN_UNICAST; |
205 | if (!fib_table_lookup(local_table, &fl, &res)) { | 213 | rcu_read_lock(); |
214 | if (!fib_table_lookup(local_table, &fl, &res, FIB_LOOKUP_NOREF)) { | ||
206 | if (!dev || dev == res.fi->fib_dev) | 215 | if (!dev || dev == res.fi->fib_dev) |
207 | ret = res.type; | 216 | ret = res.type; |
208 | fib_res_put(&res); | ||
209 | } | 217 | } |
218 | rcu_read_unlock(); | ||
210 | } | 219 | } |
211 | return ret; | 220 | return ret; |
212 | } | 221 | } |
@@ -220,30 +229,34 @@ EXPORT_SYMBOL(inet_addr_type); | |||
220 | unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, | 229 | unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, |
221 | __be32 addr) | 230 | __be32 addr) |
222 | { | 231 | { |
223 | return __inet_dev_addr_type(net, dev, addr); | 232 | return __inet_dev_addr_type(net, dev, addr); |
224 | } | 233 | } |
225 | EXPORT_SYMBOL(inet_dev_addr_type); | 234 | EXPORT_SYMBOL(inet_dev_addr_type); |
226 | 235 | ||
227 | /* Given (packet source, input interface) and optional (dst, oif, tos): | 236 | /* Given (packet source, input interface) and optional (dst, oif, tos): |
228 | - (main) check, that source is valid i.e. not broadcast or our local | 237 | * - (main) check, that source is valid i.e. not broadcast or our local |
229 | address. | 238 | * address. |
230 | - figure out what "logical" interface this packet arrived | 239 | * - figure out what "logical" interface this packet arrived |
231 | and calculate "specific destination" address. | 240 | * and calculate "specific destination" address. |
232 | - check, that packet arrived from expected physical interface. | 241 | * - check, that packet arrived from expected physical interface. |
242 | * called with rcu_read_lock() | ||
233 | */ | 243 | */ |
234 | |||
235 | int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | 244 | int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, |
236 | struct net_device *dev, __be32 *spec_dst, | 245 | struct net_device *dev, __be32 *spec_dst, |
237 | u32 *itag, u32 mark) | 246 | u32 *itag, u32 mark) |
238 | { | 247 | { |
239 | struct in_device *in_dev; | 248 | struct in_device *in_dev; |
240 | struct flowi fl = { .nl_u = { .ip4_u = | 249 | struct flowi fl = { |
241 | { .daddr = src, | 250 | .nl_u = { |
242 | .saddr = dst, | 251 | .ip4_u = { |
243 | .tos = tos } }, | 252 | .daddr = src, |
244 | .mark = mark, | 253 | .saddr = dst, |
245 | .iif = oif }; | 254 | .tos = tos |
246 | 255 | } | |
256 | }, | ||
257 | .mark = mark, | ||
258 | .iif = oif | ||
259 | }; | ||
247 | struct fib_result res; | 260 | struct fib_result res; |
248 | int no_addr, rpf, accept_local; | 261 | int no_addr, rpf, accept_local; |
249 | bool dev_match; | 262 | bool dev_match; |
@@ -251,7 +264,6 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
251 | struct net *net; | 264 | struct net *net; |
252 | 265 | ||
253 | no_addr = rpf = accept_local = 0; | 266 | no_addr = rpf = accept_local = 0; |
254 | rcu_read_lock(); | ||
255 | in_dev = __in_dev_get_rcu(dev); | 267 | in_dev = __in_dev_get_rcu(dev); |
256 | if (in_dev) { | 268 | if (in_dev) { |
257 | no_addr = in_dev->ifa_list == NULL; | 269 | no_addr = in_dev->ifa_list == NULL; |
@@ -260,7 +272,6 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
260 | if (mark && !IN_DEV_SRC_VMARK(in_dev)) | 272 | if (mark && !IN_DEV_SRC_VMARK(in_dev)) |
261 | fl.mark = 0; | 273 | fl.mark = 0; |
262 | } | 274 | } |
263 | rcu_read_unlock(); | ||
264 | 275 | ||
265 | if (in_dev == NULL) | 276 | if (in_dev == NULL) |
266 | goto e_inval; | 277 | goto e_inval; |
@@ -270,7 +281,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
270 | goto last_resort; | 281 | goto last_resort; |
271 | if (res.type != RTN_UNICAST) { | 282 | if (res.type != RTN_UNICAST) { |
272 | if (res.type != RTN_LOCAL || !accept_local) | 283 | if (res.type != RTN_LOCAL || !accept_local) |
273 | goto e_inval_res; | 284 | goto e_inval; |
274 | } | 285 | } |
275 | *spec_dst = FIB_RES_PREFSRC(res); | 286 | *spec_dst = FIB_RES_PREFSRC(res); |
276 | fib_combine_itag(itag, &res); | 287 | fib_combine_itag(itag, &res); |
@@ -291,10 +302,8 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
291 | #endif | 302 | #endif |
292 | if (dev_match) { | 303 | if (dev_match) { |
293 | ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; | 304 | ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; |
294 | fib_res_put(&res); | ||
295 | return ret; | 305 | return ret; |
296 | } | 306 | } |
297 | fib_res_put(&res); | ||
298 | if (no_addr) | 307 | if (no_addr) |
299 | goto last_resort; | 308 | goto last_resort; |
300 | if (rpf == 1) | 309 | if (rpf == 1) |
@@ -307,7 +316,6 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
307 | *spec_dst = FIB_RES_PREFSRC(res); | 316 | *spec_dst = FIB_RES_PREFSRC(res); |
308 | ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; | 317 | ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; |
309 | } | 318 | } |
310 | fib_res_put(&res); | ||
311 | } | 319 | } |
312 | return ret; | 320 | return ret; |
313 | 321 | ||
@@ -318,8 +326,6 @@ last_resort: | |||
318 | *itag = 0; | 326 | *itag = 0; |
319 | return 0; | 327 | return 0; |
320 | 328 | ||
321 | e_inval_res: | ||
322 | fib_res_put(&res); | ||
323 | e_inval: | 329 | e_inval: |
324 | return -EINVAL; | 330 | return -EINVAL; |
325 | e_rpf: | 331 | e_rpf: |
@@ -472,9 +478,9 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt, | |||
472 | } | 478 | } |
473 | 479 | ||
474 | /* | 480 | /* |
475 | * Handle IP routing ioctl calls. These are used to manipulate the routing tables | 481 | * Handle IP routing ioctl calls. |
482 | * These are used to manipulate the routing tables | ||
476 | */ | 483 | */ |
477 | |||
478 | int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg) | 484 | int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg) |
479 | { | 485 | { |
480 | struct fib_config cfg; | 486 | struct fib_config cfg; |
@@ -518,7 +524,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
518 | return -EINVAL; | 524 | return -EINVAL; |
519 | } | 525 | } |
520 | 526 | ||
521 | const struct nla_policy rtm_ipv4_policy[RTA_MAX+1] = { | 527 | const struct nla_policy rtm_ipv4_policy[RTA_MAX + 1] = { |
522 | [RTA_DST] = { .type = NLA_U32 }, | 528 | [RTA_DST] = { .type = NLA_U32 }, |
523 | [RTA_SRC] = { .type = NLA_U32 }, | 529 | [RTA_SRC] = { .type = NLA_U32 }, |
524 | [RTA_IIF] = { .type = NLA_U32 }, | 530 | [RTA_IIF] = { .type = NLA_U32 }, |
@@ -532,7 +538,7 @@ const struct nla_policy rtm_ipv4_policy[RTA_MAX+1] = { | |||
532 | }; | 538 | }; |
533 | 539 | ||
534 | static int rtm_to_fib_config(struct net *net, struct sk_buff *skb, | 540 | static int rtm_to_fib_config(struct net *net, struct sk_buff *skb, |
535 | struct nlmsghdr *nlh, struct fib_config *cfg) | 541 | struct nlmsghdr *nlh, struct fib_config *cfg) |
536 | { | 542 | { |
537 | struct nlattr *attr; | 543 | struct nlattr *attr; |
538 | int err, remaining; | 544 | int err, remaining; |
@@ -687,12 +693,11 @@ out: | |||
687 | } | 693 | } |
688 | 694 | ||
689 | /* Prepare and feed intra-kernel routing request. | 695 | /* Prepare and feed intra-kernel routing request. |
690 | Really, it should be netlink message, but :-( netlink | 696 | * Really, it should be netlink message, but :-( netlink |
691 | can be not configured, so that we feed it directly | 697 | * can be not configured, so that we feed it directly |
692 | to fib engine. It is legal, because all events occur | 698 | * to fib engine. It is legal, because all events occur |
693 | only when netlink is already locked. | 699 | * only when netlink is already locked. |
694 | */ | 700 | */ |
695 | |||
696 | static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa) | 701 | static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa) |
697 | { | 702 | { |
698 | struct net *net = dev_net(ifa->ifa_dev->dev); | 703 | struct net *net = dev_net(ifa->ifa_dev->dev); |
@@ -738,9 +743,9 @@ void fib_add_ifaddr(struct in_ifaddr *ifa) | |||
738 | struct in_ifaddr *prim = ifa; | 743 | struct in_ifaddr *prim = ifa; |
739 | __be32 mask = ifa->ifa_mask; | 744 | __be32 mask = ifa->ifa_mask; |
740 | __be32 addr = ifa->ifa_local; | 745 | __be32 addr = ifa->ifa_local; |
741 | __be32 prefix = ifa->ifa_address&mask; | 746 | __be32 prefix = ifa->ifa_address & mask; |
742 | 747 | ||
743 | if (ifa->ifa_flags&IFA_F_SECONDARY) { | 748 | if (ifa->ifa_flags & IFA_F_SECONDARY) { |
744 | prim = inet_ifa_byprefix(in_dev, prefix, mask); | 749 | prim = inet_ifa_byprefix(in_dev, prefix, mask); |
745 | if (prim == NULL) { | 750 | if (prim == NULL) { |
746 | printk(KERN_WARNING "fib_add_ifaddr: bug: prim == NULL\n"); | 751 | printk(KERN_WARNING "fib_add_ifaddr: bug: prim == NULL\n"); |
@@ -750,22 +755,24 @@ void fib_add_ifaddr(struct in_ifaddr *ifa) | |||
750 | 755 | ||
751 | fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim); | 756 | fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim); |
752 | 757 | ||
753 | if (!(dev->flags&IFF_UP)) | 758 | if (!(dev->flags & IFF_UP)) |
754 | return; | 759 | return; |
755 | 760 | ||
756 | /* Add broadcast address, if it is explicitly assigned. */ | 761 | /* Add broadcast address, if it is explicitly assigned. */ |
757 | if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF)) | 762 | if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF)) |
758 | fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim); | 763 | fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim); |
759 | 764 | ||
760 | if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) && | 765 | if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags & IFA_F_SECONDARY) && |
761 | (prefix != addr || ifa->ifa_prefixlen < 32)) { | 766 | (prefix != addr || ifa->ifa_prefixlen < 32)) { |
762 | fib_magic(RTM_NEWROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL : | 767 | fib_magic(RTM_NEWROUTE, |
763 | RTN_UNICAST, prefix, ifa->ifa_prefixlen, prim); | 768 | dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST, |
769 | prefix, ifa->ifa_prefixlen, prim); | ||
764 | 770 | ||
765 | /* Add network specific broadcasts, when it takes a sense */ | 771 | /* Add network specific broadcasts, when it takes a sense */ |
766 | if (ifa->ifa_prefixlen < 31) { | 772 | if (ifa->ifa_prefixlen < 31) { |
767 | fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim); | 773 | fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim); |
768 | fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix|~mask, 32, prim); | 774 | fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix | ~mask, |
775 | 32, prim); | ||
769 | } | 776 | } |
770 | } | 777 | } |
771 | } | 778 | } |
@@ -776,17 +783,18 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) | |||
776 | struct net_device *dev = in_dev->dev; | 783 | struct net_device *dev = in_dev->dev; |
777 | struct in_ifaddr *ifa1; | 784 | struct in_ifaddr *ifa1; |
778 | struct in_ifaddr *prim = ifa; | 785 | struct in_ifaddr *prim = ifa; |
779 | __be32 brd = ifa->ifa_address|~ifa->ifa_mask; | 786 | __be32 brd = ifa->ifa_address | ~ifa->ifa_mask; |
780 | __be32 any = ifa->ifa_address&ifa->ifa_mask; | 787 | __be32 any = ifa->ifa_address & ifa->ifa_mask; |
781 | #define LOCAL_OK 1 | 788 | #define LOCAL_OK 1 |
782 | #define BRD_OK 2 | 789 | #define BRD_OK 2 |
783 | #define BRD0_OK 4 | 790 | #define BRD0_OK 4 |
784 | #define BRD1_OK 8 | 791 | #define BRD1_OK 8 |
785 | unsigned ok = 0; | 792 | unsigned ok = 0; |
786 | 793 | ||
787 | if (!(ifa->ifa_flags&IFA_F_SECONDARY)) | 794 | if (!(ifa->ifa_flags & IFA_F_SECONDARY)) |
788 | fib_magic(RTM_DELROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL : | 795 | fib_magic(RTM_DELROUTE, |
789 | RTN_UNICAST, any, ifa->ifa_prefixlen, prim); | 796 | dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST, |
797 | any, ifa->ifa_prefixlen, prim); | ||
790 | else { | 798 | else { |
791 | prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask); | 799 | prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask); |
792 | if (prim == NULL) { | 800 | if (prim == NULL) { |
@@ -796,9 +804,9 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) | |||
796 | } | 804 | } |
797 | 805 | ||
798 | /* Deletion is more complicated than add. | 806 | /* Deletion is more complicated than add. |
799 | We should take care of not to delete too much :-) | 807 | * We should take care of not to delete too much :-) |
800 | 808 | * | |
801 | Scan address list to be sure that addresses are really gone. | 809 | * Scan address list to be sure that addresses are really gone. |
802 | */ | 810 | */ |
803 | 811 | ||
804 | for (ifa1 = in_dev->ifa_list; ifa1; ifa1 = ifa1->ifa_next) { | 812 | for (ifa1 = in_dev->ifa_list; ifa1; ifa1 = ifa1->ifa_next) { |
@@ -812,23 +820,23 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) | |||
812 | ok |= BRD0_OK; | 820 | ok |= BRD0_OK; |
813 | } | 821 | } |
814 | 822 | ||
815 | if (!(ok&BRD_OK)) | 823 | if (!(ok & BRD_OK)) |
816 | fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim); | 824 | fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim); |
817 | if (!(ok&BRD1_OK)) | 825 | if (!(ok & BRD1_OK)) |
818 | fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim); | 826 | fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim); |
819 | if (!(ok&BRD0_OK)) | 827 | if (!(ok & BRD0_OK)) |
820 | fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32, prim); | 828 | fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32, prim); |
821 | if (!(ok&LOCAL_OK)) { | 829 | if (!(ok & LOCAL_OK)) { |
822 | fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim); | 830 | fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim); |
823 | 831 | ||
824 | /* Check, that this local address finally disappeared. */ | 832 | /* Check, that this local address finally disappeared. */ |
825 | if (inet_addr_type(dev_net(dev), ifa->ifa_local) != RTN_LOCAL) { | 833 | if (inet_addr_type(dev_net(dev), ifa->ifa_local) != RTN_LOCAL) { |
826 | /* And the last, but not the least thing. | 834 | /* And the last, but not the least thing. |
827 | We must flush stray FIB entries. | 835 | * We must flush stray FIB entries. |
828 | 836 | * | |
829 | First of all, we scan fib_info list searching | 837 | * First of all, we scan fib_info list searching |
830 | for stray nexthop entries, then ignite fib_flush. | 838 | * for stray nexthop entries, then ignite fib_flush. |
831 | */ | 839 | */ |
832 | if (fib_sync_down_addr(dev_net(dev), ifa->ifa_local)) | 840 | if (fib_sync_down_addr(dev_net(dev), ifa->ifa_local)) |
833 | fib_flush(dev_net(dev)); | 841 | fib_flush(dev_net(dev)); |
834 | } | 842 | } |
@@ -839,14 +847,20 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) | |||
839 | #undef BRD1_OK | 847 | #undef BRD1_OK |
840 | } | 848 | } |
841 | 849 | ||
842 | static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) | 850 | static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb) |
843 | { | 851 | { |
844 | 852 | ||
845 | struct fib_result res; | 853 | struct fib_result res; |
846 | struct flowi fl = { .mark = frn->fl_mark, | 854 | struct flowi fl = { |
847 | .nl_u = { .ip4_u = { .daddr = frn->fl_addr, | 855 | .mark = frn->fl_mark, |
848 | .tos = frn->fl_tos, | 856 | .nl_u = { |
849 | .scope = frn->fl_scope } } }; | 857 | .ip4_u = { |
858 | .daddr = frn->fl_addr, | ||
859 | .tos = frn->fl_tos, | ||
860 | .scope = frn->fl_scope | ||
861 | } | ||
862 | } | ||
863 | }; | ||
850 | 864 | ||
851 | #ifdef CONFIG_IP_MULTIPLE_TABLES | 865 | #ifdef CONFIG_IP_MULTIPLE_TABLES |
852 | res.r = NULL; | 866 | res.r = NULL; |
@@ -857,15 +871,16 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) | |||
857 | local_bh_disable(); | 871 | local_bh_disable(); |
858 | 872 | ||
859 | frn->tb_id = tb->tb_id; | 873 | frn->tb_id = tb->tb_id; |
860 | frn->err = fib_table_lookup(tb, &fl, &res); | 874 | rcu_read_lock(); |
875 | frn->err = fib_table_lookup(tb, &fl, &res, FIB_LOOKUP_NOREF); | ||
861 | 876 | ||
862 | if (!frn->err) { | 877 | if (!frn->err) { |
863 | frn->prefixlen = res.prefixlen; | 878 | frn->prefixlen = res.prefixlen; |
864 | frn->nh_sel = res.nh_sel; | 879 | frn->nh_sel = res.nh_sel; |
865 | frn->type = res.type; | 880 | frn->type = res.type; |
866 | frn->scope = res.scope; | 881 | frn->scope = res.scope; |
867 | fib_res_put(&res); | ||
868 | } | 882 | } |
883 | rcu_read_unlock(); | ||
869 | local_bh_enable(); | 884 | local_bh_enable(); |
870 | } | 885 | } |
871 | } | 886 | } |
@@ -894,8 +909,8 @@ static void nl_fib_input(struct sk_buff *skb) | |||
894 | 909 | ||
895 | nl_fib_lookup(frn, tb); | 910 | nl_fib_lookup(frn, tb); |
896 | 911 | ||
897 | pid = NETLINK_CB(skb).pid; /* pid of sending process */ | 912 | pid = NETLINK_CB(skb).pid; /* pid of sending process */ |
898 | NETLINK_CB(skb).pid = 0; /* from kernel */ | 913 | NETLINK_CB(skb).pid = 0; /* from kernel */ |
899 | NETLINK_CB(skb).dst_group = 0; /* unicast */ | 914 | NETLINK_CB(skb).dst_group = 0; /* unicast */ |
900 | netlink_unicast(net->ipv4.fibnl, skb, pid, MSG_DONTWAIT); | 915 | netlink_unicast(net->ipv4.fibnl, skb, pid, MSG_DONTWAIT); |
901 | } | 916 | } |
@@ -942,7 +957,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
942 | fib_del_ifaddr(ifa); | 957 | fib_del_ifaddr(ifa); |
943 | if (ifa->ifa_dev->ifa_list == NULL) { | 958 | if (ifa->ifa_dev->ifa_list == NULL) { |
944 | /* Last address was deleted from this interface. | 959 | /* Last address was deleted from this interface. |
945 | Disable IP. | 960 | * Disable IP. |
946 | */ | 961 | */ |
947 | fib_disable_ip(dev, 1, 0); | 962 | fib_disable_ip(dev, 1, 0); |
948 | } else { | 963 | } else { |
@@ -1001,16 +1016,15 @@ static struct notifier_block fib_netdev_notifier = { | |||
1001 | static int __net_init ip_fib_net_init(struct net *net) | 1016 | static int __net_init ip_fib_net_init(struct net *net) |
1002 | { | 1017 | { |
1003 | int err; | 1018 | int err; |
1004 | unsigned int i; | 1019 | size_t size = sizeof(struct hlist_head) * FIB_TABLE_HASHSZ; |
1005 | 1020 | ||
1006 | net->ipv4.fib_table_hash = kzalloc( | 1021 | /* Avoid false sharing : Use at least a full cache line */ |
1007 | sizeof(struct hlist_head)*FIB_TABLE_HASHSZ, GFP_KERNEL); | 1022 | size = max_t(size_t, size, L1_CACHE_BYTES); |
1023 | |||
1024 | net->ipv4.fib_table_hash = kzalloc(size, GFP_KERNEL); | ||
1008 | if (net->ipv4.fib_table_hash == NULL) | 1025 | if (net->ipv4.fib_table_hash == NULL) |
1009 | return -ENOMEM; | 1026 | return -ENOMEM; |
1010 | 1027 | ||
1011 | for (i = 0; i < FIB_TABLE_HASHSZ; i++) | ||
1012 | INIT_HLIST_HEAD(&net->ipv4.fib_table_hash[i]); | ||
1013 | |||
1014 | err = fib4_rules_init(net); | 1028 | err = fib4_rules_init(net); |
1015 | if (err < 0) | 1029 | if (err < 0) |
1016 | goto fail; | 1030 | goto fail; |