Lines Matching refs:fi

62 #define for_nexthops(fi) {						\  argument
64 for (nhsel = 0, nh = (fi)->fib_nh; \
65 nhsel < (fi)->fib_nhs; \
68 #define change_nexthops(fi) { \ argument
70 for (nhsel = 0, nexthop_nh = (struct fib_nh *)((fi)->fib_nh); \
71 nhsel < (fi)->fib_nhs; \
78 #define for_nexthops(fi) { \ argument
79 int nhsel; const struct fib_nh *nh = (fi)->fib_nh; \
82 #define change_nexthops(fi) { \ argument
84 struct fib_nh *nexthop_nh = (struct fib_nh *)((fi)->fib_nh); \
89 #define endfor_nexthops(fi) } argument
206 struct fib_info *fi = container_of(head, struct fib_info, rcu); in free_fib_info_rcu() local
208 change_nexthops(fi) { in free_fib_info_rcu()
214 } endfor_nexthops(fi); in free_fib_info_rcu()
216 if (fi->fib_metrics != (u32 *) dst_default_metrics) in free_fib_info_rcu()
217 kfree(fi->fib_metrics); in free_fib_info_rcu()
218 kfree(fi); in free_fib_info_rcu()
221 void free_fib_info(struct fib_info *fi) in free_fib_info() argument
223 if (fi->fib_dead == 0) { in free_fib_info()
224 pr_warn("Freeing alive fib_info %p\n", fi); in free_fib_info()
229 change_nexthops(fi) { in free_fib_info()
231 fi->fib_net->ipv4.fib_num_tclassid_users--; in free_fib_info()
232 } endfor_nexthops(fi); in free_fib_info()
234 call_rcu(&fi->rcu, free_fib_info_rcu); in free_fib_info()
237 void fib_release_info(struct fib_info *fi) in fib_release_info() argument
240 if (fi && --fi->fib_treeref == 0) { in fib_release_info()
241 hlist_del(&fi->fib_hash); in fib_release_info()
242 if (fi->fib_prefsrc) in fib_release_info()
243 hlist_del(&fi->fib_lhash); in fib_release_info()
244 change_nexthops(fi) { in fib_release_info()
248 } endfor_nexthops(fi) in fib_release_info()
249 fi->fib_dead = 1; in fib_release_info()
250 fib_info_put(fi); in fib_release_info()
255 static inline int nh_comp(const struct fib_info *fi, const struct fib_info *ofi) in nh_comp() argument
259 for_nexthops(fi) { in nh_comp()
272 } endfor_nexthops(fi); in nh_comp()
285 static inline unsigned int fib_info_hashfn(const struct fib_info *fi) in fib_info_hashfn() argument
288 unsigned int val = fi->fib_nhs; in fib_info_hashfn()
290 val ^= (fi->fib_protocol << 8) | fi->fib_scope; in fib_info_hashfn()
291 val ^= (__force u32)fi->fib_prefsrc; in fib_info_hashfn()
292 val ^= fi->fib_priority; in fib_info_hashfn()
293 for_nexthops(fi) { in fib_info_hashfn()
295 } endfor_nexthops(fi) in fib_info_hashfn()
303 struct fib_info *fi; in fib_find_info() local
309 hlist_for_each_entry(fi, head, fib_hash) { in fib_find_info()
310 if (!net_eq(fi->fib_net, nfi->fib_net)) in fib_find_info()
312 if (fi->fib_nhs != nfi->fib_nhs) in fib_find_info()
314 if (nfi->fib_protocol == fi->fib_protocol && in fib_find_info()
315 nfi->fib_scope == fi->fib_scope && in fib_find_info()
316 nfi->fib_prefsrc == fi->fib_prefsrc && in fib_find_info()
317 nfi->fib_priority == fi->fib_priority && in fib_find_info()
318 nfi->fib_type == fi->fib_type && in fib_find_info()
319 memcmp(nfi->fib_metrics, fi->fib_metrics, in fib_find_info()
321 ((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_F_DEAD) == 0 && in fib_find_info()
322 (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0)) in fib_find_info()
323 return fi; in fib_find_info()
356 static inline size_t fib_nlmsg_size(struct fib_info *fi) in fib_nlmsg_size() argument
368 if (fi->fib_nhs) { in fib_nlmsg_size()
378 payload += nla_total_size(fi->fib_nhs * nhsize); in fib_nlmsg_size()
413 static int fib_detect_death(struct fib_info *fi, int order, in fib_detect_death() argument
420 n = neigh_lookup(&arp_tbl, &fi->fib_nh[0].nh_gw, fi->fib_dev); in fib_detect_death()
431 *last_resort = fi; in fib_detect_death()
452 static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, in fib_get_nhs() argument
455 change_nexthops(fi) { in fib_get_nhs()
476 fi->fib_net->ipv4.fib_num_tclassid_users++; in fib_get_nhs()
481 } endfor_nexthops(fi); in fib_get_nhs()
488 int fib_nh_match(struct fib_config *cfg, struct fib_info *fi) in fib_nh_match() argument
495 if (cfg->fc_priority && cfg->fc_priority != fi->fib_priority) in fib_nh_match()
499 if ((!cfg->fc_oif || cfg->fc_oif == fi->fib_nh->nh_oif) && in fib_nh_match()
500 (!cfg->fc_gw || cfg->fc_gw == fi->fib_nh->nh_gw)) in fib_nh_match()
512 for_nexthops(fi) { in fib_nh_match()
536 } endfor_nexthops(fi); in fib_nh_match()
585 static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, in fib_check_nh() argument
710 struct fib_info *fi; in fib_info_hash_move() local
712 hlist_for_each_entry_safe(fi, n, head, fib_hash) { in fib_info_hash_move()
716 hlist_del(&fi->fib_hash); in fib_info_hash_move()
718 new_hash = fib_info_hashfn(fi); in fib_info_hash_move()
720 hlist_add_head(&fi->fib_hash, dest); in fib_info_hash_move()
728 struct fib_info *fi; in fib_info_hash_move() local
730 hlist_for_each_entry_safe(fi, n, lhead, fib_lhash) { in fib_info_hash_move()
734 hlist_del(&fi->fib_lhash); in fib_info_hash_move()
736 new_hash = fib_laddr_hashfn(fi->fib_prefsrc); in fib_info_hash_move()
738 hlist_add_head(&fi->fib_lhash, ldest); in fib_info_hash_move()
763 struct fib_info *fi = NULL; in fib_create_info() local
805 fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL); in fib_create_info()
806 if (!fi) in fib_create_info()
810 fi->fib_metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); in fib_create_info()
811 if (!fi->fib_metrics) in fib_create_info()
814 fi->fib_metrics = (u32 *) dst_default_metrics; in fib_create_info()
816 fi->fib_net = net; in fib_create_info()
817 fi->fib_protocol = cfg->fc_protocol; in fib_create_info()
818 fi->fib_scope = cfg->fc_scope; in fib_create_info()
819 fi->fib_flags = cfg->fc_flags; in fib_create_info()
820 fi->fib_priority = cfg->fc_priority; in fib_create_info()
821 fi->fib_prefsrc = cfg->fc_prefsrc; in fib_create_info()
822 fi->fib_type = cfg->fc_type; in fib_create_info()
824 fi->fib_nhs = nhs; in fib_create_info()
825 change_nexthops(fi) { in fib_create_info()
826 nexthop_nh->nh_parent = fi; in fib_create_info()
830 } endfor_nexthops(fi) in fib_create_info()
858 fi->fib_metrics[type - 1] = val; in fib_create_info()
865 err = fib_get_nhs(fi, cfg->fc_mp, cfg->fc_mp_len, cfg); in fib_create_info()
868 if (cfg->fc_oif && fi->fib_nh->nh_oif != cfg->fc_oif) in fib_create_info()
870 if (cfg->fc_gw && fi->fib_nh->nh_gw != cfg->fc_gw) in fib_create_info()
873 if (cfg->fc_flow && fi->fib_nh->nh_tclassid != cfg->fc_flow) in fib_create_info()
880 struct fib_nh *nh = fi->fib_nh; in fib_create_info()
888 fi->fib_net->ipv4.fib_num_tclassid_users++; in fib_create_info()
916 struct fib_nh *nh = fi->fib_nh; in fib_create_info()
922 nh->nh_dev = dev_get_by_index(net, fi->fib_nh->nh_oif); in fib_create_info()
927 change_nexthops(fi) { in fib_create_info()
928 err = fib_check_nh(cfg, fi, nexthop_nh); in fib_create_info()
931 } endfor_nexthops(fi) in fib_create_info()
934 if (fi->fib_prefsrc) { in fib_create_info()
936 fi->fib_prefsrc != cfg->fc_dst) in fib_create_info()
937 if (inet_addr_type(net, fi->fib_prefsrc) != RTN_LOCAL) in fib_create_info()
941 change_nexthops(fi) { in fib_create_info()
943 } endfor_nexthops(fi) in fib_create_info()
946 ofi = fib_find_info(fi); in fib_create_info()
948 fi->fib_dead = 1; in fib_create_info()
949 free_fib_info(fi); in fib_create_info()
954 fi->fib_treeref++; in fib_create_info()
955 atomic_inc(&fi->fib_clntref); in fib_create_info()
957 hlist_add_head(&fi->fib_hash, in fib_create_info()
958 &fib_info_hash[fib_info_hashfn(fi)]); in fib_create_info()
959 if (fi->fib_prefsrc) { in fib_create_info()
962 head = &fib_info_laddrhash[fib_laddr_hashfn(fi->fib_prefsrc)]; in fib_create_info()
963 hlist_add_head(&fi->fib_lhash, head); in fib_create_info()
965 change_nexthops(fi) { in fib_create_info()
974 } endfor_nexthops(fi) in fib_create_info()
976 return fi; in fib_create_info()
982 if (fi) { in fib_create_info()
983 fi->fib_dead = 1; in fib_create_info()
984 free_fib_info(fi); in fib_create_info()
992 struct fib_info *fi, unsigned int flags) in fib_dump_info() argument
1013 rtm->rtm_flags = fi->fib_flags; in fib_dump_info()
1014 rtm->rtm_scope = fi->fib_scope; in fib_dump_info()
1015 rtm->rtm_protocol = fi->fib_protocol; in fib_dump_info()
1020 if (fi->fib_priority && in fib_dump_info()
1021 nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority)) in fib_dump_info()
1023 if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0) in fib_dump_info()
1026 if (fi->fib_prefsrc && in fib_dump_info()
1027 nla_put_in_addr(skb, RTA_PREFSRC, fi->fib_prefsrc)) in fib_dump_info()
1029 if (fi->fib_nhs == 1) { in fib_dump_info()
1030 if (fi->fib_nh->nh_gw && in fib_dump_info()
1031 nla_put_in_addr(skb, RTA_GATEWAY, fi->fib_nh->nh_gw)) in fib_dump_info()
1033 if (fi->fib_nh->nh_oif && in fib_dump_info()
1034 nla_put_u32(skb, RTA_OIF, fi->fib_nh->nh_oif)) in fib_dump_info()
1037 if (fi->fib_nh[0].nh_tclassid && in fib_dump_info()
1038 nla_put_u32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid)) in fib_dump_info()
1043 if (fi->fib_nhs > 1) { in fib_dump_info()
1051 for_nexthops(fi) { in fib_dump_info()
1070 } endfor_nexthops(fi); in fib_dump_info()
1094 struct fib_info *fi; in fib_sync_down_addr() local
1099 hlist_for_each_entry(fi, head, fib_lhash) { in fib_sync_down_addr()
1100 if (!net_eq(fi->fib_net, net)) in fib_sync_down_addr()
1102 if (fi->fib_prefsrc == local) { in fib_sync_down_addr()
1103 fi->fib_flags |= RTNH_F_DEAD; in fib_sync_down_addr()
1123 struct fib_info *fi = nh->nh_parent; in fib_sync_down_dev() local
1126 BUG_ON(!fi->fib_nhs); in fib_sync_down_dev()
1127 if (nh->nh_dev != dev || fi == prev_fi) in fib_sync_down_dev()
1129 prev_fi = fi; in fib_sync_down_dev()
1131 change_nexthops(fi) { in fib_sync_down_dev()
1139 fi->fib_power -= nexthop_nh->nh_power; in fib_sync_down_dev()
1147 dead = fi->fib_nhs; in fib_sync_down_dev()
1151 } endfor_nexthops(fi) in fib_sync_down_dev()
1152 if (dead == fi->fib_nhs) { in fib_sync_down_dev()
1153 fi->fib_flags |= RTNH_F_DEAD; in fib_sync_down_dev()
1164 struct fib_info *fi = NULL, *last_resort = NULL; in fib_select_default() local
1177 if (next_fi->fib_priority > res->fi->fib_priority) in fib_select_default()
1185 if (!fi) { in fib_select_default()
1186 if (next_fi != res->fi) in fib_select_default()
1188 } else if (!fib_detect_death(fi, order, &last_resort, in fib_select_default()
1190 fib_result_assign(res, fi); in fib_select_default()
1194 fi = next_fi; in fib_select_default()
1198 if (order <= 0 || !fi) { in fib_select_default()
1203 if (!fib_detect_death(fi, order, &last_resort, &last_idx, in fib_select_default()
1205 fib_result_assign(res, fi); in fib_select_default()
1240 struct fib_info *fi = nh->nh_parent; in fib_sync_up() local
1243 BUG_ON(!fi->fib_nhs); in fib_sync_up()
1244 if (nh->nh_dev != dev || fi == prev_fi) in fib_sync_up()
1247 prev_fi = fi; in fib_sync_up()
1249 change_nexthops(fi) { in fib_sync_up()
1265 } endfor_nexthops(fi) in fib_sync_up()
1268 fi->fib_flags &= ~RTNH_F_DEAD; in fib_sync_up()
1282 struct fib_info *fi = res->fi; in fib_select_multipath() local
1286 if (fi->fib_power <= 0) { in fib_select_multipath()
1288 change_nexthops(fi) { in fib_select_multipath()
1293 } endfor_nexthops(fi); in fib_select_multipath()
1294 fi->fib_power = power; in fib_select_multipath()
1308 w = jiffies % fi->fib_power; in fib_select_multipath()
1310 change_nexthops(fi) { in fib_select_multipath()
1316 fi->fib_power--; in fib_select_multipath()
1322 } endfor_nexthops(fi); in fib_select_multipath()