Lines Matching refs:fi

67 #define for_nexthops(fi) {						\
69 for (nhsel = 0, nh = (fi)->fib_nh; \
70 nhsel < fib_info_num_path((fi)); \
73 #define change_nexthops(fi) { \
75 for (nhsel = 0, nexthop_nh = (struct fib_nh *)((fi)->fib_nh); \
76 nhsel < fib_info_num_path((fi)); \
83 #define for_nexthops(fi) { \
84 int nhsel; const struct fib_nh *nh = (fi)->fib_nh; \
87 #define change_nexthops(fi) { \
89 struct fib_nh *nexthop_nh = (struct fib_nh *)((fi)->fib_nh); \
94 #define endfor_nexthops(fi) }
235 struct fib_info *fi = container_of(head, struct fib_info, rcu);
237 if (fi->nh) {
238 nexthop_put(fi->nh);
240 change_nexthops(fi) {
241 fib_nh_release(fi->fib_net, nexthop_nh);
242 } endfor_nexthops(fi);
245 ip_fib_metrics_put(fi->fib_metrics);
247 kfree(fi);
250 void free_fib_info(struct fib_info *fi)
252 if (fi->fib_dead == 0) {
253 pr_warn("Freeing alive fib_info %p\n", fi);
257 call_rcu(&fi->rcu, free_fib_info_rcu);
261 void fib_release_info(struct fib_info *fi)
264 if (fi && --fi->fib_treeref == 0) {
265 hlist_del(&fi->fib_hash);
270 if (fi->fib_prefsrc)
271 hlist_del(&fi->fib_lhash);
272 if (fi->nh) {
273 list_del(&fi->nh_list);
275 change_nexthops(fi) {
279 } endfor_nexthops(fi)
282 WRITE_ONCE(fi->fib_dead, 1);
283 fib_info_put(fi);
288 static inline int nh_comp(struct fib_info *fi, struct fib_info *ofi)
292 if (fi->nh || ofi->nh)
293 return nexthop_cmp(fi->nh, ofi->nh) ? 0 : -1;
298 for_nexthops(fi) {
321 } endfor_nexthops(fi);
357 static inline unsigned int fib_info_hashfn(struct fib_info *fi)
361 val = fib_info_hashfn_1(fi->fib_nhs, fi->fib_protocol,
362 fi->fib_scope, (__force u32)fi->fib_prefsrc,
363 fi->fib_priority);
365 if (fi->nh) {
366 val ^= fib_devindex_hashfn(fi->nh->id);
368 for_nexthops(fi) {
370 } endfor_nexthops(fi)
381 struct fib_info *fi;
391 hlist_for_each_entry(fi, head, fib_hash) {
392 if (!net_eq(fi->fib_net, net))
394 if (!fi->nh || fi->nh->id != cfg->fc_nh_id)
396 if (cfg->fc_protocol == fi->fib_protocol &&
397 cfg->fc_scope == fi->fib_scope &&
398 cfg->fc_prefsrc == fi->fib_prefsrc &&
399 cfg->fc_priority == fi->fib_priority &&
400 cfg->fc_type == fi->fib_type &&
401 cfg->fc_table == fi->fib_tb_id &&
402 !((cfg->fc_flags ^ fi->fib_flags) & ~RTNH_COMPARE_MASK))
403 return fi;
412 struct fib_info *fi;
418 hlist_for_each_entry(fi, head, fib_hash) {
419 if (!net_eq(fi->fib_net, nfi->fib_net))
421 if (fi->fib_nhs != nfi->fib_nhs)
423 if (nfi->fib_protocol == fi->fib_protocol &&
424 nfi->fib_scope == fi->fib_scope &&
425 nfi->fib_prefsrc == fi->fib_prefsrc &&
426 nfi->fib_priority == fi->fib_priority &&
427 nfi->fib_type == fi->fib_type &&
428 nfi->fib_tb_id == fi->fib_tb_id &&
429 memcmp(nfi->fib_metrics, fi->fib_metrics,
431 !((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_COMPARE_MASK) &&
432 nh_comp(fi, nfi) == 0)
433 return fi;
465 static inline size_t fib_nlmsg_size(struct fib_info *fi)
473 unsigned int nhs = fib_info_num_path(fi);
478 if (fi->nh)
493 for (i = 0; i < fib_info_num_path(fi); i++) {
494 struct fib_nh_common *nhc = fib_info_nhc(fi, i);
526 fri.fi = fa->fa_info;
549 static int fib_detect_death(struct fib_info *fi, int order,
553 const struct fib_nh_common *nhc = fib_info_nhc(fi, 0);
577 *last_resort = fi;
690 static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
694 struct net *net = fi->fib_net;
699 change_nexthops(fi) {
768 } endfor_nexthops(fi);
771 nh = fib_info_nh(fi, 0);
801 static void fib_rebalance(struct fib_info *fi)
806 if (fib_info_num_path(fi) < 2)
810 for_nexthops(fi) {
819 } endfor_nexthops(fi);
822 change_nexthops(fi) {
837 } endfor_nexthops(fi);
841 static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
850 #define fib_rebalance(fi) do { } while (0)
876 int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi,
884 if (cfg->fc_priority && cfg->fc_priority != fi->fib_priority)
888 if (fi->nh && cfg->fc_nh_id == fi->nh->id)
893 if (fi->nh) {
902 nh = fib_info_nh(fi, 0);
936 for_nexthops(fi) {
1004 } endfor_nexthops(fi);
1009 bool fib_metrics_match(struct fib_config *cfg, struct fib_info *fi)
1032 val = tcp_ca_get_key_by_name(fi->fib_net, tmp, &ecn_ca);
1039 fi_val = fi->fib_metrics->metrics[type - 1];
1308 struct fib_info *fi;
1310 hlist_for_each_entry_safe(fi, n, head, fib_hash) {
1314 new_hash = fib_info_hashfn(fi);
1316 hlist_add_head(&fi->fib_hash, dest);
1324 struct fib_info *fi;
1326 hlist_for_each_entry_safe(fi, n, lhead, fib_lhash) {
1330 new_hash = fib_laddr_hashfn(fi->fib_prefsrc);
1332 hlist_add_head(&fi->fib_lhash, ldest);
1366 if (res->fi->fib_prefsrc)
1367 return res->fi->fib_prefsrc;
1378 return fib_info_update_nhc_saddr(net, nhc, res->fi->fib_scope);
1409 struct fib_info *fi = NULL;
1432 fi = fib_find_info_nh(net, cfg);
1433 if (fi) {
1434 fi->fib_treeref++;
1435 return fi;
1479 fi = kzalloc(struct_size(fi, fib_nh, nhs), GFP_KERNEL);
1480 if (!fi)
1482 fi->fib_metrics = ip_fib_metrics_init(fi->fib_net, cfg->fc_mx,
1484 if (IS_ERR(fi->fib_metrics)) {
1485 err = PTR_ERR(fi->fib_metrics);
1486 kfree(fi);
1490 fi->fib_net = net;
1491 fi->fib_protocol = cfg->fc_protocol;
1492 fi->fib_scope = cfg->fc_scope;
1493 fi->fib_flags = cfg->fc_flags;
1494 fi->fib_priority = cfg->fc_priority;
1495 fi->fib_prefsrc = cfg->fc_prefsrc;
1496 fi->fib_type = cfg->fc_type;
1497 fi->fib_tb_id = cfg->fc_table;
1499 fi->fib_nhs = nhs;
1506 fi->nh = nh;
1509 change_nexthops(fi) {
1510 nexthop_nh->nh_parent = fi;
1511 } endfor_nexthops(fi)
1514 err = fib_get_nhs(fi, cfg->fc_mp, cfg->fc_mp_len, cfg,
1517 err = fib_nh_init(net, fi->fib_nh, cfg, 1, extack);
1549 if (fi->nh) {
1550 err = fib_check_nexthop(fi->nh, cfg->fc_scope, extack);
1554 struct fib_nh *nh = fi->fib_nh;
1575 change_nexthops(fi) {
1583 } endfor_nexthops(fi)
1584 if (linkdown == fi->fib_nhs)
1585 fi->fib_flags |= RTNH_F_LINKDOWN;
1588 if (fi->fib_prefsrc && !fib_valid_prefsrc(cfg, fi->fib_prefsrc)) {
1593 if (!fi->nh) {
1594 change_nexthops(fi) {
1596 fi->fib_scope);
1598 fi->fib_nh_is_v6 = true;
1599 } endfor_nexthops(fi)
1601 fib_rebalance(fi);
1605 ofi = fib_find_info(fi);
1607 /* fib_table_lookup() should not see @fi yet. */
1608 fi->fib_dead = 1;
1609 free_fib_info(fi);
1614 fi->fib_treeref++;
1615 refcount_set(&fi->fib_clntref, 1);
1618 hlist_add_head(&fi->fib_hash,
1619 &fib_info_hash[fib_info_hashfn(fi)]);
1620 if (fi->fib_prefsrc) {
1623 head = &fib_info_laddrhash[fib_laddr_hashfn(fi->fib_prefsrc)];
1624 hlist_add_head(&fi->fib_lhash, head);
1626 if (fi->nh) {
1627 list_add(&fi->nh_list, &nh->fi_list);
1629 change_nexthops(fi) {
1636 } endfor_nexthops(fi)
1639 return fi;
1645 if (fi) {
1646 /* fib_table_lookup() should not see @fi yet. */
1647 fi->fib_dead = 1;
1648 free_fib_info(fi);
1760 static int fib_add_multipath(struct sk_buff *skb, struct fib_info *fi)
1768 if (unlikely(fi->nh)) {
1769 if (nexthop_mpath_fill_node(skb, fi->nh, AF_INET) < 0)
1774 for_nexthops(fi) {
1782 } endfor_nexthops(fi);
1793 static int fib_add_multipath(struct sk_buff *skb, struct fib_info *fi)
1802 unsigned int nhs = fib_info_num_path(fri->fi);
1803 struct fib_info *fi = fri->fi;
1824 rtm->rtm_flags = fi->fib_flags;
1825 rtm->rtm_scope = fi->fib_scope;
1826 rtm->rtm_protocol = fi->fib_protocol;
1831 if (fi->fib_priority &&
1832 nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority))
1834 if (rtnetlink_put_metrics(skb, fi->fib_metrics->metrics) < 0)
1837 if (fi->fib_prefsrc &&
1838 nla_put_in_addr(skb, RTA_PREFSRC, fi->fib_prefsrc))
1841 if (fi->nh) {
1842 if (nla_put_u32(skb, RTA_NH_ID, fi->nh->id))
1844 if (nexthop_is_blackhole(fi->nh))
1846 if (!READ_ONCE(fi->fib_net->ipv4.sysctl_nexthop_compat_mode))
1851 const struct fib_nh_common *nhc = fib_info_nhc(fi, 0);
1869 if (fib_add_multipath(skb, fi) < 0)
1900 struct fib_info *fi;
1905 hlist_for_each_entry(fi, head, fib_lhash) {
1906 if (!net_eq(fi->fib_net, net) ||
1907 fi->fib_tb_id != tb_id)
1909 if (fi->fib_prefsrc == local) {
1910 fi->fib_flags |= RTNH_F_DEAD;
1911 fi->pfsrc_removed = true;
2015 struct fib_info *fi = nh->nh_parent;
2018 BUG_ON(!fi->fib_nhs);
2019 if (nh->fib_nh_dev != dev || fi == prev_fi)
2021 prev_fi = fi;
2023 change_nexthops(fi) {
2044 dead = fi->fib_nhs;
2048 } endfor_nexthops(fi)
2049 if (dead == fi->fib_nhs) {
2053 fi->fib_flags |= RTNH_F_DEAD;
2056 fi->fib_flags |= RTNH_F_LINKDOWN;
2062 fib_rebalance(fi);
2071 struct fib_info *fi = NULL, *last_resort = NULL;
2077 u32 last_prio = res->fi->fib_priority;
2111 if (!fi) {
2112 if (next_fi != res->fi)
2115 } else if (!fib_detect_death(fi, order, &last_resort,
2117 fib_result_assign(res, fi);
2121 fi = next_fi;
2125 if (order <= 0 || !fi) {
2131 if (!fib_detect_death(fi, order, &last_resort, &last_idx,
2133 fib_result_assign(res, fi);
2173 struct fib_info *fi = nh->nh_parent;
2176 BUG_ON(!fi->fib_nhs);
2177 if (nh->fib_nh_dev != dev || fi == prev_fi)
2180 prev_fi = fi;
2182 change_nexthops(fi) {
2196 } endfor_nexthops(fi)
2199 fi->fib_flags &= ~nh_flags;
2203 fib_rebalance(fi);
2238 struct fib_info *fi = res->fi;
2239 struct net *net = fi->fib_net;
2242 if (unlikely(res->fi->nh)) {
2247 change_nexthops(fi) {
2264 } endfor_nexthops(fi);
2275 if (fib_info_num_path(res->fi) > 1) {