diff options
Diffstat (limited to 'net/ipv4/fib_semantics.c')
-rw-r--r-- | net/ipv4/fib_semantics.c | 85 |
1 files changed, 43 insertions, 42 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 9b096d6ff3f2..20f09c5b31e8 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/proc_fs.h> | 32 | #include <linux/proc_fs.h> |
33 | #include <linux/skbuff.h> | 33 | #include <linux/skbuff.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/slab.h> | ||
35 | 36 | ||
36 | #include <net/arp.h> | 37 | #include <net/arp.h> |
37 | #include <net/ip.h> | 38 | #include <net/ip.h> |
@@ -62,8 +63,8 @@ static DEFINE_SPINLOCK(fib_multipath_lock); | |||
62 | #define for_nexthops(fi) { int nhsel; const struct fib_nh * nh; \ | 63 | #define for_nexthops(fi) { int nhsel; const struct fib_nh * nh; \ |
63 | for (nhsel=0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++) | 64 | for (nhsel=0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++) |
64 | 65 | ||
65 | #define change_nexthops(fi) { int nhsel; struct fib_nh * nh; \ | 66 | #define change_nexthops(fi) { int nhsel; struct fib_nh *nexthop_nh; \ |
66 | for (nhsel=0, nh = (struct fib_nh *)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nh++, nhsel++) | 67 | for (nhsel=0, nexthop_nh = (struct fib_nh *)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nexthop_nh++, nhsel++) |
67 | 68 | ||
68 | #else /* CONFIG_IP_ROUTE_MULTIPATH */ | 69 | #else /* CONFIG_IP_ROUTE_MULTIPATH */ |
69 | 70 | ||
@@ -72,7 +73,7 @@ for (nhsel=0, nh = (struct fib_nh *)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nh++, | |||
72 | #define for_nexthops(fi) { int nhsel = 0; const struct fib_nh * nh = (fi)->fib_nh; \ | 73 | #define for_nexthops(fi) { int nhsel = 0; const struct fib_nh * nh = (fi)->fib_nh; \ |
73 | for (nhsel=0; nhsel < 1; nhsel++) | 74 | for (nhsel=0; nhsel < 1; nhsel++) |
74 | 75 | ||
75 | #define change_nexthops(fi) { int nhsel = 0; struct fib_nh * nh = (struct fib_nh *)((fi)->fib_nh); \ | 76 | #define change_nexthops(fi) { int nhsel = 0; struct fib_nh *nexthop_nh = (struct fib_nh *)((fi)->fib_nh); \ |
76 | for (nhsel=0; nhsel < 1; nhsel++) | 77 | for (nhsel=0; nhsel < 1; nhsel++) |
77 | 78 | ||
78 | #endif /* CONFIG_IP_ROUTE_MULTIPATH */ | 79 | #endif /* CONFIG_IP_ROUTE_MULTIPATH */ |
@@ -145,9 +146,9 @@ void free_fib_info(struct fib_info *fi) | |||
145 | return; | 146 | return; |
146 | } | 147 | } |
147 | change_nexthops(fi) { | 148 | change_nexthops(fi) { |
148 | if (nh->nh_dev) | 149 | if (nexthop_nh->nh_dev) |
149 | dev_put(nh->nh_dev); | 150 | dev_put(nexthop_nh->nh_dev); |
150 | nh->nh_dev = NULL; | 151 | nexthop_nh->nh_dev = NULL; |
151 | } endfor_nexthops(fi); | 152 | } endfor_nexthops(fi); |
152 | fib_info_cnt--; | 153 | fib_info_cnt--; |
153 | release_net(fi->fib_net); | 154 | release_net(fi->fib_net); |
@@ -162,9 +163,9 @@ void fib_release_info(struct fib_info *fi) | |||
162 | if (fi->fib_prefsrc) | 163 | if (fi->fib_prefsrc) |
163 | hlist_del(&fi->fib_lhash); | 164 | hlist_del(&fi->fib_lhash); |
164 | change_nexthops(fi) { | 165 | change_nexthops(fi) { |
165 | if (!nh->nh_dev) | 166 | if (!nexthop_nh->nh_dev) |
166 | continue; | 167 | continue; |
167 | hlist_del(&nh->nh_hash); | 168 | hlist_del(&nexthop_nh->nh_hash); |
168 | } endfor_nexthops(fi) | 169 | } endfor_nexthops(fi) |
169 | fi->fib_dead = 1; | 170 | fi->fib_dead = 1; |
170 | fib_info_put(fi); | 171 | fib_info_put(fi); |
@@ -228,7 +229,7 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi) | |||
228 | head = &fib_info_hash[hash]; | 229 | head = &fib_info_hash[hash]; |
229 | 230 | ||
230 | hlist_for_each_entry(fi, node, head, fib_hash) { | 231 | hlist_for_each_entry(fi, node, head, fib_hash) { |
231 | if (fi->fib_net != nfi->fib_net) | 232 | if (!net_eq(fi->fib_net, nfi->fib_net)) |
232 | continue; | 233 | continue; |
233 | if (fi->fib_nhs != nfi->fib_nhs) | 234 | if (fi->fib_nhs != nfi->fib_nhs) |
234 | continue; | 235 | continue; |
@@ -395,19 +396,20 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, | |||
395 | if (!rtnh_ok(rtnh, remaining)) | 396 | if (!rtnh_ok(rtnh, remaining)) |
396 | return -EINVAL; | 397 | return -EINVAL; |
397 | 398 | ||
398 | nh->nh_flags = (cfg->fc_flags & ~0xFF) | rtnh->rtnh_flags; | 399 | nexthop_nh->nh_flags = |
399 | nh->nh_oif = rtnh->rtnh_ifindex; | 400 | (cfg->fc_flags & ~0xFF) | rtnh->rtnh_flags; |
400 | nh->nh_weight = rtnh->rtnh_hops + 1; | 401 | nexthop_nh->nh_oif = rtnh->rtnh_ifindex; |
402 | nexthop_nh->nh_weight = rtnh->rtnh_hops + 1; | ||
401 | 403 | ||
402 | attrlen = rtnh_attrlen(rtnh); | 404 | attrlen = rtnh_attrlen(rtnh); |
403 | if (attrlen > 0) { | 405 | if (attrlen > 0) { |
404 | struct nlattr *nla, *attrs = rtnh_attrs(rtnh); | 406 | struct nlattr *nla, *attrs = rtnh_attrs(rtnh); |
405 | 407 | ||
406 | nla = nla_find(attrs, attrlen, RTA_GATEWAY); | 408 | nla = nla_find(attrs, attrlen, RTA_GATEWAY); |
407 | nh->nh_gw = nla ? nla_get_be32(nla) : 0; | 409 | nexthop_nh->nh_gw = nla ? nla_get_be32(nla) : 0; |
408 | #ifdef CONFIG_NET_CLS_ROUTE | 410 | #ifdef CONFIG_NET_CLS_ROUTE |
409 | nla = nla_find(attrs, attrlen, RTA_FLOW); | 411 | nla = nla_find(attrs, attrlen, RTA_FLOW); |
410 | nh->nh_tclassid = nla ? nla_get_u32(nla) : 0; | 412 | nexthop_nh->nh_tclassid = nla ? nla_get_u32(nla) : 0; |
411 | #endif | 413 | #endif |
412 | } | 414 | } |
413 | 415 | ||
@@ -527,10 +529,6 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, | |||
527 | if (nh->nh_gw) { | 529 | if (nh->nh_gw) { |
528 | struct fib_result res; | 530 | struct fib_result res; |
529 | 531 | ||
530 | #ifdef CONFIG_IP_ROUTE_PERVASIVE | ||
531 | if (nh->nh_flags&RTNH_F_PERVASIVE) | ||
532 | return 0; | ||
533 | #endif | ||
534 | if (nh->nh_flags&RTNH_F_ONLINK) { | 532 | if (nh->nh_flags&RTNH_F_ONLINK) { |
535 | struct net_device *dev; | 533 | struct net_device *dev; |
536 | 534 | ||
@@ -738,7 +736,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) | |||
738 | 736 | ||
739 | fi->fib_nhs = nhs; | 737 | fi->fib_nhs = nhs; |
740 | change_nexthops(fi) { | 738 | change_nexthops(fi) { |
741 | nh->nh_parent = fi; | 739 | nexthop_nh->nh_parent = fi; |
742 | } endfor_nexthops(fi) | 740 | } endfor_nexthops(fi) |
743 | 741 | ||
744 | if (cfg->fc_mx) { | 742 | if (cfg->fc_mx) { |
@@ -808,7 +806,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) | |||
808 | goto failure; | 806 | goto failure; |
809 | } else { | 807 | } else { |
810 | change_nexthops(fi) { | 808 | change_nexthops(fi) { |
811 | if ((err = fib_check_nh(cfg, fi, nh)) != 0) | 809 | if ((err = fib_check_nh(cfg, fi, nexthop_nh)) != 0) |
812 | goto failure; | 810 | goto failure; |
813 | } endfor_nexthops(fi) | 811 | } endfor_nexthops(fi) |
814 | } | 812 | } |
@@ -843,11 +841,11 @@ link_it: | |||
843 | struct hlist_head *head; | 841 | struct hlist_head *head; |
844 | unsigned int hash; | 842 | unsigned int hash; |
845 | 843 | ||
846 | if (!nh->nh_dev) | 844 | if (!nexthop_nh->nh_dev) |
847 | continue; | 845 | continue; |
848 | hash = fib_devindex_hashfn(nh->nh_dev->ifindex); | 846 | hash = fib_devindex_hashfn(nexthop_nh->nh_dev->ifindex); |
849 | head = &fib_info_devhash[hash]; | 847 | head = &fib_info_devhash[hash]; |
850 | hlist_add_head(&nh->nh_hash, head); | 848 | hlist_add_head(&nexthop_nh->nh_hash, head); |
851 | } endfor_nexthops(fi) | 849 | } endfor_nexthops(fi) |
852 | spin_unlock_bh(&fib_info_lock); | 850 | spin_unlock_bh(&fib_info_lock); |
853 | return fi; | 851 | return fi; |
@@ -1047,7 +1045,7 @@ int fib_sync_down_addr(struct net *net, __be32 local) | |||
1047 | return 0; | 1045 | return 0; |
1048 | 1046 | ||
1049 | hlist_for_each_entry(fi, node, head, fib_lhash) { | 1047 | hlist_for_each_entry(fi, node, head, fib_lhash) { |
1050 | if (fi->fib_net != net) | 1048 | if (!net_eq(fi->fib_net, net)) |
1051 | continue; | 1049 | continue; |
1052 | if (fi->fib_prefsrc == local) { | 1050 | if (fi->fib_prefsrc == local) { |
1053 | fi->fib_flags |= RTNH_F_DEAD; | 1051 | fi->fib_flags |= RTNH_F_DEAD; |
@@ -1080,21 +1078,21 @@ int fib_sync_down_dev(struct net_device *dev, int force) | |||
1080 | prev_fi = fi; | 1078 | prev_fi = fi; |
1081 | dead = 0; | 1079 | dead = 0; |
1082 | change_nexthops(fi) { | 1080 | change_nexthops(fi) { |
1083 | if (nh->nh_flags&RTNH_F_DEAD) | 1081 | if (nexthop_nh->nh_flags&RTNH_F_DEAD) |
1084 | dead++; | 1082 | dead++; |
1085 | else if (nh->nh_dev == dev && | 1083 | else if (nexthop_nh->nh_dev == dev && |
1086 | nh->nh_scope != scope) { | 1084 | nexthop_nh->nh_scope != scope) { |
1087 | nh->nh_flags |= RTNH_F_DEAD; | 1085 | nexthop_nh->nh_flags |= RTNH_F_DEAD; |
1088 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 1086 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
1089 | spin_lock_bh(&fib_multipath_lock); | 1087 | spin_lock_bh(&fib_multipath_lock); |
1090 | fi->fib_power -= nh->nh_power; | 1088 | fi->fib_power -= nexthop_nh->nh_power; |
1091 | nh->nh_power = 0; | 1089 | nexthop_nh->nh_power = 0; |
1092 | spin_unlock_bh(&fib_multipath_lock); | 1090 | spin_unlock_bh(&fib_multipath_lock); |
1093 | #endif | 1091 | #endif |
1094 | dead++; | 1092 | dead++; |
1095 | } | 1093 | } |
1096 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 1094 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
1097 | if (force > 1 && nh->nh_dev == dev) { | 1095 | if (force > 1 && nexthop_nh->nh_dev == dev) { |
1098 | dead = fi->fib_nhs; | 1096 | dead = fi->fib_nhs; |
1099 | break; | 1097 | break; |
1100 | } | 1098 | } |
@@ -1144,18 +1142,20 @@ int fib_sync_up(struct net_device *dev) | |||
1144 | prev_fi = fi; | 1142 | prev_fi = fi; |
1145 | alive = 0; | 1143 | alive = 0; |
1146 | change_nexthops(fi) { | 1144 | change_nexthops(fi) { |
1147 | if (!(nh->nh_flags&RTNH_F_DEAD)) { | 1145 | if (!(nexthop_nh->nh_flags&RTNH_F_DEAD)) { |
1148 | alive++; | 1146 | alive++; |
1149 | continue; | 1147 | continue; |
1150 | } | 1148 | } |
1151 | if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP)) | 1149 | if (nexthop_nh->nh_dev == NULL || |
1150 | !(nexthop_nh->nh_dev->flags&IFF_UP)) | ||
1152 | continue; | 1151 | continue; |
1153 | if (nh->nh_dev != dev || !__in_dev_get_rtnl(dev)) | 1152 | if (nexthop_nh->nh_dev != dev || |
1153 | !__in_dev_get_rtnl(dev)) | ||
1154 | continue; | 1154 | continue; |
1155 | alive++; | 1155 | alive++; |
1156 | spin_lock_bh(&fib_multipath_lock); | 1156 | spin_lock_bh(&fib_multipath_lock); |
1157 | nh->nh_power = 0; | 1157 | nexthop_nh->nh_power = 0; |
1158 | nh->nh_flags &= ~RTNH_F_DEAD; | 1158 | nexthop_nh->nh_flags &= ~RTNH_F_DEAD; |
1159 | spin_unlock_bh(&fib_multipath_lock); | 1159 | spin_unlock_bh(&fib_multipath_lock); |
1160 | } endfor_nexthops(fi) | 1160 | } endfor_nexthops(fi) |
1161 | 1161 | ||
@@ -1182,9 +1182,9 @@ void fib_select_multipath(const struct flowi *flp, struct fib_result *res) | |||
1182 | if (fi->fib_power <= 0) { | 1182 | if (fi->fib_power <= 0) { |
1183 | int power = 0; | 1183 | int power = 0; |
1184 | change_nexthops(fi) { | 1184 | change_nexthops(fi) { |
1185 | if (!(nh->nh_flags&RTNH_F_DEAD)) { | 1185 | if (!(nexthop_nh->nh_flags&RTNH_F_DEAD)) { |
1186 | power += nh->nh_weight; | 1186 | power += nexthop_nh->nh_weight; |
1187 | nh->nh_power = nh->nh_weight; | 1187 | nexthop_nh->nh_power = nexthop_nh->nh_weight; |
1188 | } | 1188 | } |
1189 | } endfor_nexthops(fi); | 1189 | } endfor_nexthops(fi); |
1190 | fi->fib_power = power; | 1190 | fi->fib_power = power; |
@@ -1204,9 +1204,10 @@ void fib_select_multipath(const struct flowi *flp, struct fib_result *res) | |||
1204 | w = jiffies % fi->fib_power; | 1204 | w = jiffies % fi->fib_power; |
1205 | 1205 | ||
1206 | change_nexthops(fi) { | 1206 | change_nexthops(fi) { |
1207 | if (!(nh->nh_flags&RTNH_F_DEAD) && nh->nh_power) { | 1207 | if (!(nexthop_nh->nh_flags&RTNH_F_DEAD) && |
1208 | if ((w -= nh->nh_power) <= 0) { | 1208 | nexthop_nh->nh_power) { |
1209 | nh->nh_power--; | 1209 | if ((w -= nexthop_nh->nh_power) <= 0) { |
1210 | nexthop_nh->nh_power--; | ||
1210 | fi->fib_power--; | 1211 | fi->fib_power--; |
1211 | res->nh_sel = nhsel; | 1212 | res->nh_sel = nhsel; |
1212 | spin_unlock_bh(&fib_multipath_lock); | 1213 | spin_unlock_bh(&fib_multipath_lock); |