Lines Matching refs:nh

22 static void remove_nexthop(struct net *net, struct nexthop *nh,
100 const struct nexthop *nh) in nh_notifier_single_info_init() argument
102 struct nh_info *nhi = rtnl_dereference(nh->nh_info); in nh_notifier_single_info_init()
105 info->nh = kzalloc(sizeof(*info->nh), GFP_KERNEL); in nh_notifier_single_info_init()
106 if (!info->nh) in nh_notifier_single_info_init()
109 __nh_notifier_single_info_init(info->nh, nhi); in nh_notifier_single_info_init()
116 kfree(info->nh); in nh_notifier_single_info_fini()
138 nhi = rtnl_dereference(nhge->nh->nh_info); in nh_notifier_mpath_info_init()
139 info->nh_grp->nh_entries[i].id = nhge->nh->id; in nh_notifier_mpath_info_init()
141 __nh_notifier_single_info_init(&info->nh_grp->nh_entries[i].nh, in nh_notifier_mpath_info_init()
171 nhi = rtnl_dereference(nhge->nh->nh_info); in nh_notifier_res_table_info_init()
180 const struct nexthop *nh) in nh_notifier_grp_info_init() argument
182 struct nh_group *nhg = rtnl_dereference(nh->nh_grp); in nh_notifier_grp_info_init()
192 const struct nexthop *nh) in nh_notifier_grp_info_fini() argument
194 struct nh_group *nhg = rtnl_dereference(nh->nh_grp); in nh_notifier_grp_info_fini()
203 const struct nexthop *nh) in nh_notifier_info_init() argument
205 info->id = nh->id; in nh_notifier_info_init()
207 if (nh->is_group) in nh_notifier_info_init()
208 return nh_notifier_grp_info_init(info, nh); in nh_notifier_info_init()
210 return nh_notifier_single_info_init(info, nh); in nh_notifier_info_init()
214 const struct nexthop *nh) in nh_notifier_info_fini() argument
216 if (nh->is_group) in nh_notifier_info_fini()
217 nh_notifier_grp_info_fini(info, nh); in nh_notifier_info_fini()
224 struct nexthop *nh, in call_nexthop_notifiers() argument
238 err = nh_notifier_info_init(&info, nh); in call_nexthop_notifiers()
246 nh_notifier_info_fini(&info, nh); in call_nexthop_notifiers()
257 struct nexthop *nh; in nh_notifier_res_bucket_idle_timer_get() local
276 nh = nexthop_find_by_id(info->net, info->id); in nh_notifier_res_bucket_idle_timer_get()
277 if (!nh) { in nh_notifier_res_bucket_idle_timer_get()
282 nhg = rcu_dereference(nh->nh_grp); in nh_notifier_res_bucket_idle_timer_get()
389 static int call_nexthop_res_table_notifiers(struct net *net, struct nexthop *nh, in call_nexthop_res_table_notifiers() argument
408 nhg = rtnl_dereference(nh->nh_grp); in call_nexthop_res_table_notifiers()
425 struct nexthop *nh, in call_nexthop_notifier() argument
434 err = nh_notifier_info_init(&info, nh); in call_nexthop_notifier()
439 nh_notifier_info_fini(&info, nh); in call_nexthop_notifier()
466 static void nexthop_free_group(struct nexthop *nh) in nexthop_free_group() argument
471 nhg = rcu_dereference_raw(nh->nh_grp); in nexthop_free_group()
476 nexthop_put(nhge->nh); in nexthop_free_group()
488 static void nexthop_free_single(struct nexthop *nh) in nexthop_free_single() argument
492 nhi = rcu_dereference_raw(nh->nh_info); in nexthop_free_single()
495 fib_nh_release(nh->net, &nhi->fib_nh); in nexthop_free_single()
506 struct nexthop *nh = container_of(head, struct nexthop, rcu); in nexthop_free_rcu() local
508 if (nh->is_group) in nexthop_free_rcu()
509 nexthop_free_group(nh); in nexthop_free_rcu()
511 nexthop_free_single(nh); in nexthop_free_rcu()
513 kfree(nh); in nexthop_free_rcu()
519 struct nexthop *nh; in nexthop_alloc() local
521 nh = kzalloc(sizeof(struct nexthop), GFP_KERNEL); in nexthop_alloc()
522 if (nh) { in nexthop_alloc()
523 INIT_LIST_HEAD(&nh->fi_list); in nexthop_alloc()
524 INIT_LIST_HEAD(&nh->f6i_list); in nexthop_alloc()
525 INIT_LIST_HEAD(&nh->grp_list); in nexthop_alloc()
526 INIT_LIST_HEAD(&nh->fdb_list); in nexthop_alloc()
528 return nh; in nexthop_alloc()
579 struct nexthop *nh; in nexthop_find_by_id() local
586 nh = rb_entry(parent, struct nexthop, rb_node); in nexthop_find_by_id()
587 if (id < nh->id) in nexthop_find_by_id()
589 else if (id > nh->id) in nexthop_find_by_id()
592 return nh; in nexthop_find_by_id()
678 p->id = nhg->nh_entries[i].nh->id; in nla_put_nh_group()
692 static int nh_fill_node(struct sk_buff *skb, struct nexthop *nh, in nh_fill_node() argument
707 nhm->nh_flags = nh->nh_flags; in nh_fill_node()
708 nhm->nh_protocol = nh->protocol; in nh_fill_node()
712 if (nla_put_u32(skb, NHA_ID, nh->id)) in nh_fill_node()
715 if (nh->is_group) { in nh_fill_node()
716 struct nh_group *nhg = rtnl_dereference(nh->nh_grp); in nh_fill_node()
725 nhi = rtnl_dereference(nh->nh_info); in nh_fill_node()
782 static size_t nh_nlmsg_size_grp(struct nexthop *nh) in nh_nlmsg_size_grp() argument
784 struct nh_group *nhg = rtnl_dereference(nh->nh_grp); in nh_nlmsg_size_grp()
795 static size_t nh_nlmsg_size_single(struct nexthop *nh) in nh_nlmsg_size_single() argument
797 struct nh_info *nhi = rtnl_dereference(nh->nh_info); in nh_nlmsg_size_single()
826 static size_t nh_nlmsg_size(struct nexthop *nh) in nh_nlmsg_size() argument
832 if (nh->is_group) in nh_nlmsg_size()
833 sz += nh_nlmsg_size_grp(nh); in nh_nlmsg_size()
835 sz += nh_nlmsg_size_single(nh); in nh_nlmsg_size()
840 static void nexthop_notify(int event, struct nexthop *nh, struct nl_info *info) in nexthop_notify() argument
847 skb = nlmsg_new(nh_nlmsg_size(nh), gfp_any()); in nexthop_notify()
851 err = nh_fill_node(skb, nh, event, info->portid, seq, nlflags); in nexthop_notify()
913 static int nh_fill_res_bucket(struct sk_buff *skb, struct nexthop *nh, in nh_fill_res_bucket() argument
931 nhm->nh_protocol = nh->protocol; in nh_fill_res_bucket()
935 if (nla_put_u32(skb, NHA_ID, nh->id)) in nh_fill_res_bucket()
943 nla_put_u32(skb, NHA_RES_BUCKET_NH_ID, nhge->nh->id) || in nh_fill_res_bucket()
965 struct nexthop *nh = nhge->nh_parent; in nexthop_bucket_notify() local
973 err = nh_fill_res_bucket(skb, nh, bucket, bucket_index, in nexthop_bucket_notify()
981 rtnl_notify(skb, nh->net, 0, RTNLGRP_NEXTHOP, NULL, GFP_KERNEL); in nexthop_bucket_notify()
985 rtnl_set_sk_err(nh->net, RTNLGRP_NEXTHOP, err); in nexthop_bucket_notify()
988 static bool valid_group_nh(struct nexthop *nh, unsigned int npaths, in valid_group_nh() argument
991 if (nh->is_group) { in valid_group_nh()
992 struct nh_group *nhg = rtnl_dereference(nh->nh_grp); in valid_group_nh()
1007 struct nh_info *nhi = rtnl_dereference(nh->nh_info); in valid_group_nh()
1020 static int nh_check_attr_fdb_group(struct nexthop *nh, u8 *nh_family, in nh_check_attr_fdb_group() argument
1025 nhi = rtnl_dereference(nh->nh_info); in nh_check_attr_fdb_group()
1083 struct nexthop *nh; in nh_check_attr_group() local
1086 nh = nexthop_find_by_id(net, nhg[i].id); in nh_check_attr_group()
1087 if (!nh) { in nh_check_attr_group()
1091 if (!valid_group_nh(nh, len, &is_fdb_nh, extack)) in nh_check_attr_group()
1094 if (nhg_fdb && nh_check_attr_fdb_group(nh, &nh_family, extack)) in nh_check_attr_group()
1121 static bool ipv6_good_nh(const struct fib6_nh *nh) in ipv6_good_nh() argument
1128 n = __ipv6_neigh_lookup_noref_stub(nh->fib_nh_dev, &nh->fib_nh_gw6); in ipv6_good_nh()
1137 static bool ipv4_good_nh(const struct fib_nh *nh) in ipv4_good_nh() argument
1144 n = __ipv4_neigh_lookup_noref(nh->fib_nh_dev, in ipv4_good_nh()
1145 (__force u32)nh->fib_nh_gw4); in ipv4_good_nh()
1166 nhi = rcu_dereference(nhge->nh->nh_info); in nexthop_select_path_hthr()
1168 return nhge->nh; in nexthop_select_path_hthr()
1176 return nhge->nh; in nexthop_select_path_hthr()
1180 return nhge->nh; in nexthop_select_path_hthr()
1185 rc = nhge->nh; in nexthop_select_path_hthr()
1204 return nhge->nh; in nexthop_select_path_res()
1207 struct nexthop *nexthop_select_path(struct nexthop *nh, int hash) in nexthop_select_path() argument
1211 if (!nh->is_group) in nexthop_select_path()
1212 return nh; in nexthop_select_path()
1214 nhg = rcu_dereference(nh->nh_grp); in nexthop_select_path()
1225 int nexthop_for_each_fib6_nh(struct nexthop *nh, in nexthop_for_each_fib6_nh() argument
1226 int (*cb)(struct fib6_nh *nh, void *arg), in nexthop_for_each_fib6_nh() argument
1232 if (nh->is_group) { in nexthop_for_each_fib6_nh()
1236 nhg = rcu_dereference_rtnl(nh->nh_grp); in nexthop_for_each_fib6_nh()
1240 nhi = rcu_dereference_rtnl(nhge->nh->nh_info); in nexthop_for_each_fib6_nh()
1246 nhi = rcu_dereference_rtnl(nh->nh_info); in nexthop_for_each_fib6_nh()
1266 int fib6_check_nexthop(struct nexthop *nh, struct fib6_config *cfg, in fib6_check_nexthop() argument
1281 if (nh->is_group) { in fib6_check_nexthop()
1284 nhg = rtnl_dereference(nh->nh_grp); in fib6_check_nexthop()
1289 nhi = rtnl_dereference(nh->nh_info); in fib6_check_nexthop()
1347 int fib_check_nexthop(struct nexthop *nh, u8 scope, in fib_check_nexthop() argument
1353 if (nh->is_group) { in fib_check_nexthop()
1356 nhg = rtnl_dereference(nh->nh_grp); in fib_check_nexthop()
1370 nhi = rtnl_dereference(nhg->nh_entries[0].nh->nh_info); in fib_check_nexthop()
1373 nhi = rtnl_dereference(nh->nh_info); in fib_check_nexthop()
1527 old_nhge->nh, in nh_res_bucket_migrate()
1528 new_nhge->nh, &extack); in nh_res_bucket_migrate()
1673 u32 id = rtnl_dereference(bucket->nh_entry)->nh->id; in nh_res_table_migrate_buckets()
1680 if (nhge->nh->id == id) { in nh_res_table_migrate_buckets()
1738 struct nexthop *nh = nhge->nh; in remove_nh_grp_entry() local
1742 WARN_ON(!nh); in remove_nh_grp_entry()
1767 if (nhg->nh_entries[i].nh == nh) { in remove_nh_grp_entry()
1772 nhi = rtnl_dereference(nhges[i].nh->nh_info); in remove_nh_grp_entry()
1778 new_nhges[j].nh = nhges[i].nh; in remove_nh_grp_entry()
1780 list_add(&new_nhges[j].nh_list, &new_nhges[j].nh->grp_list); in remove_nh_grp_entry()
1792 nexthop_put(nhge->nh); in remove_nh_grp_entry()
1808 static void remove_nexthop_from_groups(struct net *net, struct nexthop *nh, in remove_nexthop_from_groups() argument
1813 list_for_each_entry_safe(nhge, tmp, &nh->grp_list, nh_list) in remove_nexthop_from_groups()
1820 static void remove_nexthop_group(struct nexthop *nh, struct nl_info *nlinfo) in remove_nexthop_group() argument
1822 struct nh_group *nhg = rcu_dereference_rtnl(nh->nh_grp); in remove_nexthop_group()
1829 if (WARN_ON(!nhge->nh)) in remove_nexthop_group()
1842 static void __remove_nexthop_fib(struct net *net, struct nexthop *nh) in __remove_nexthop_fib() argument
1848 list_for_each_entry(fi, &nh->fi_list, nh_list) { in __remove_nexthop_fib()
1856 list_for_each_entry_safe(f6i, tmp, &nh->f6i_list, nh_list) { in __remove_nexthop_fib()
1864 static void __remove_nexthop(struct net *net, struct nexthop *nh, in __remove_nexthop() argument
1867 __remove_nexthop_fib(net, nh); in __remove_nexthop()
1869 if (nh->is_group) { in __remove_nexthop()
1870 remove_nexthop_group(nh, nlinfo); in __remove_nexthop()
1874 nhi = rtnl_dereference(nh->nh_info); in __remove_nexthop()
1878 remove_nexthop_from_groups(net, nh, nlinfo); in __remove_nexthop()
1882 static void remove_nexthop(struct net *net, struct nexthop *nh, in remove_nexthop() argument
1885 call_nexthop_notifiers(net, NEXTHOP_EVENT_DEL, nh, NULL); in remove_nexthop()
1888 rb_erase(&nh->rb_node, &net->nexthop.rb_root); in remove_nexthop()
1891 nexthop_notify(RTM_DELNEXTHOP, nh, nlinfo); in remove_nexthop()
1893 __remove_nexthop(net, nh, nlinfo); in remove_nexthop()
1896 nexthop_put(nh); in remove_nexthop()
1902 static void nh_rt_cache_flush(struct net *net, struct nexthop *nh, in nh_rt_cache_flush() argument
1909 if (!list_empty(&nh->fi_list)) in nh_rt_cache_flush()
1912 list_for_each_entry(f6i, &nh->f6i_list, nh_list) in nh_rt_cache_flush()
1927 struct nh_info *nhi = rtnl_dereference(nhge->nh->nh_info); in nh_rt_cache_flush()
2030 nhi = rtnl_dereference(nhges[i].nh->nh_info); in nh_group_v4_update()
2053 if (nhge->nh == old) { in replace_nexthop_single_notify_res()
2071 if (nhge->nh == old) in replace_nexthop_single_notify_res()
2181 static void __nexthop_replace_notify(struct net *net, struct nexthop *nh, in __nexthop_replace_notify() argument
2186 if (!list_empty(&nh->fi_list)) { in __nexthop_replace_notify()
2193 list_for_each_entry(fi, &nh->fi_list, nh_list) in __nexthop_replace_notify()
2198 list_for_each_entry(fi, &nh->fi_list, nh_list) in __nexthop_replace_notify()
2202 list_for_each_entry(f6i, &nh->f6i_list, nh_list) in __nexthop_replace_notify()
2210 static void nexthop_replace_notify(struct net *net, struct nexthop *nh, in nexthop_replace_notify() argument
2215 __nexthop_replace_notify(net, nh, info); in nexthop_replace_notify()
2217 list_for_each_entry(nhge, &nh->grp_list, nh_list) in nexthop_replace_notify()
2294 struct nexthop *nh; in insert_nexthop() local
2302 nh = rb_entry(parent, struct nexthop, rb_node); in insert_nexthop()
2303 if (new_id < nh->id) { in insert_nexthop()
2305 } else if (new_id > nh->id) { in insert_nexthop()
2308 rc = replace_nexthop(net, nh, new_nh, cfg, extack); in insert_nexthop()
2310 new_nh = nh; /* send notification with old nh */ in insert_nexthop()
2399 struct nexthop *nh; in flush_all_nexthops() local
2402 nh = rb_entry(node, struct nexthop, rb_node); in flush_all_nexthops()
2403 remove_nexthop(net, nh, NULL); in flush_all_nexthops()
2415 struct nexthop *nh; in nexthop_create_group() local
2422 nh = nexthop_alloc(); in nexthop_create_group()
2423 if (!nh) in nexthop_create_group()
2426 nh->is_group = 1; in nexthop_create_group()
2430 kfree(nh); in nexthop_create_group()
2438 kfree(nh); in nexthop_create_group()
2457 nhg->nh_entries[i].nh = nhe; in nexthop_create_group()
2460 nhg->nh_entries[i].nh_parent = nh; in nexthop_create_group()
2489 rcu_assign_pointer(nh->nh_grp, nhg); in nexthop_create_group()
2491 return nh; in nexthop_create_group()
2496 nexthop_put(nhg->nh_entries[i].nh); in nexthop_create_group()
2501 kfree(nh); in nexthop_create_group()
2506 static int nh_create_ipv4(struct net *net, struct nexthop *nh, in nh_create_ipv4() argument
2535 nh->nh_flags = fib_nh->fib_nh_flags; in nh_create_ipv4()
2545 static int nh_create_ipv6(struct net *net, struct nexthop *nh, in nh_create_ipv6() argument
2574 nh->nh_flags = fib6_nh->fib_nh_flags; in nh_create_ipv6()
2584 struct nexthop *nh; in nexthop_create() local
2587 nh = nexthop_alloc(); in nexthop_create()
2588 if (!nh) in nexthop_create()
2593 kfree(nh); in nexthop_create()
2597 nh->nh_flags = cfg->nh_flags; in nexthop_create()
2598 nh->net = net; in nexthop_create()
2600 nhi->nh_parent = nh; in nexthop_create()
2614 err = nh_create_ipv4(net, nh, nhi, cfg, extack); in nexthop_create()
2617 err = nh_create_ipv6(net, nh, nhi, cfg, extack); in nexthop_create()
2623 kfree(nh); in nexthop_create()
2631 rcu_assign_pointer(nh->nh_info, nhi); in nexthop_create()
2633 return nh; in nexthop_create()
2640 struct nexthop *nh; in nexthop_add() local
2657 nh = nexthop_create_group(net, cfg); in nexthop_add()
2659 nh = nexthop_create(net, cfg, extack); in nexthop_add()
2661 if (IS_ERR(nh)) in nexthop_add()
2662 return nh; in nexthop_add()
2664 refcount_set(&nh->refcnt, 1); in nexthop_add()
2665 nh->id = cfg->nh_id; in nexthop_add()
2666 nh->protocol = cfg->nh_protocol; in nexthop_add()
2667 nh->net = net; in nexthop_add()
2669 err = insert_nexthop(net, nh, cfg, extack); in nexthop_add()
2671 __remove_nexthop(net, nh, NULL); in nexthop_add()
2672 nexthop_put(nh); in nexthop_add()
2673 nh = ERR_PTR(err); in nexthop_add()
2676 return nh; in nexthop_add()
2933 struct nexthop *nh; in rtm_new_nexthop() local
2938 nh = nexthop_add(net, &cfg, extack); in rtm_new_nexthop()
2939 if (IS_ERR(nh)) in rtm_new_nexthop()
2940 err = PTR_ERR(nh); in rtm_new_nexthop()
2996 struct nexthop *nh; in rtm_del_nexthop() local
3004 nh = nexthop_find_by_id(net, id); in rtm_del_nexthop()
3005 if (!nh) in rtm_del_nexthop()
3008 remove_nexthop(net, nh, &nlinfo); in rtm_del_nexthop()
3019 struct nexthop *nh; in rtm_get_nexthop() local
3033 nh = nexthop_find_by_id(net, id); in rtm_get_nexthop()
3034 if (!nh) in rtm_get_nexthop()
3037 err = nh_fill_node(skb, nh, RTM_NEWNEXTHOP, NETLINK_CB(in_skb).portid, in rtm_get_nexthop()
3061 static bool nh_dump_filtered(struct nexthop *nh, in nh_dump_filtered() argument
3067 if (filter->group_filter && !nh->is_group) in nh_dump_filtered()
3073 if (nh->is_group) in nh_dump_filtered()
3076 nhi = rtnl_dereference(nh->nh_info); in nh_dump_filtered()
3168 struct nexthop *nh, void *data), in rtm_dump_walk_nexthops() argument
3177 struct nexthop *nh; in rtm_dump_walk_nexthops() local
3179 nh = rb_entry(node, struct nexthop, rb_node); in rtm_dump_walk_nexthops()
3180 if (nh->id < s_idx) in rtm_dump_walk_nexthops()
3183 ctx->idx = nh->id; in rtm_dump_walk_nexthops()
3184 err = nh_cb(skb, cb, nh, data); in rtm_dump_walk_nexthops()
3194 struct nexthop *nh, void *data) in rtm_dump_nexthop_cb() argument
3199 if (nh_dump_filtered(nh, filter, nhm->nh_family)) in rtm_dump_nexthop_cb()
3202 return nh_fill_node(skb, nh, RTM_NEWNEXTHOP, in rtm_dump_nexthop_cb()
3241 struct nexthop *nh; in nexthop_find_group_resilient() local
3243 nh = nexthop_find_by_id(net, id); in nexthop_find_group_resilient()
3244 if (!nh) in nexthop_find_group_resilient()
3247 if (!nh->is_group) { in nexthop_find_group_resilient()
3252 nhg = rtnl_dereference(nh->nh_grp); in nexthop_find_group_resilient()
3258 return nh; in nexthop_find_group_resilient()
3319 struct rtm_dump_nh_ctx nh; member
3340 struct nexthop *nh, in rtm_dump_nexthop_bucket_nh() argument
3350 if (dd->ctx->nh.idx < dd->ctx->done_nh_idx) in rtm_dump_nexthop_bucket_nh()
3353 nhg = rtnl_dereference(nh->nh_grp); in rtm_dump_nexthop_bucket_nh()
3363 if (nh_dump_filtered(nhge->nh, &dd->filter, nhm->nh_family)) in rtm_dump_nexthop_bucket_nh()
3367 dd->filter.res_bucket_nh_id != nhge->nh->id) in rtm_dump_nexthop_bucket_nh()
3370 err = nh_fill_res_bucket(skb, nh, bucket, bucket_index, in rtm_dump_nexthop_bucket_nh()
3381 dd->ctx->done_nh_idx = dd->ctx->nh.idx + 1; in rtm_dump_nexthop_bucket_nh()
3393 struct nexthop *nh, void *data) in rtm_dump_nexthop_bucket_cb() argument
3398 if (!nh->is_group) in rtm_dump_nexthop_bucket_cb()
3401 nhg = rtnl_dereference(nh->nh_grp); in rtm_dump_nexthop_bucket_cb()
3405 return rtm_dump_nexthop_bucket_nh(skb, cb, nh, dd); in rtm_dump_nexthop_bucket_cb()
3415 struct nexthop *nh; in rtm_dump_nexthop_bucket() local
3423 nh = nexthop_find_group_resilient(net, dd.filter.nh_id, in rtm_dump_nexthop_bucket()
3425 if (IS_ERR(nh)) in rtm_dump_nexthop_bucket()
3426 return PTR_ERR(nh); in rtm_dump_nexthop_bucket()
3427 err = rtm_dump_nexthop_bucket_nh(skb, cb, nh, &dd); in rtm_dump_nexthop_bucket()
3431 err = rtm_dump_walk_nexthops(skb, cb, root, &ctx->nh, in rtm_dump_nexthop_bucket()
3508 struct nexthop *nh; in rtm_get_nexthop_bucket() local
3517 nh = nexthop_find_group_resilient(net, id, extack); in rtm_get_nexthop_bucket()
3518 if (IS_ERR(nh)) in rtm_get_nexthop_bucket()
3519 return PTR_ERR(nh); in rtm_get_nexthop_bucket()
3521 nhg = rtnl_dereference(nh->nh_grp); in rtm_get_nexthop_bucket()
3532 err = nh_fill_res_bucket(skb, nh, &res_table->nh_buckets[bucket_index], in rtm_get_nexthop_bucket()
3603 struct nexthop *nh; in nexthops_dump() local
3605 nh = rb_entry(node, struct nexthop, rb_node); in nexthops_dump()
3606 err = call_nexthop_notifier(nb, net, event_type, nh, extack); in nexthops_dump()