diff options
Diffstat (limited to 'net/ipv4/fib_semantics.c')
| -rw-r--r-- | net/ipv4/fib_semantics.c | 81 |
1 files changed, 41 insertions, 40 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index ed19aa6919c2..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); |
| @@ -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; |
| @@ -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); |
