aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_semantics.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/fib_semantics.c')
-rw-r--r--net/ipv4/fib_semantics.c85
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; \
63for (nhsel=0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++) 64for (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; \
66for (nhsel=0, nh = (struct fib_nh *)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nh++, nhsel++) 67for (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; \
73for (nhsel=0; nhsel < 1; nhsel++) 74for (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); \
76for (nhsel=0; nhsel < 1; nhsel++) 77for (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);