Lines Matching refs:nh
19 static void remove_nexthop(struct net *net, struct nexthop *nh,
41 struct nexthop *nh) in call_nexthop_notifiers() argument
46 event_type, nh); in call_nexthop_notifiers()
72 static void nexthop_free_mpath(struct nexthop *nh) in nexthop_free_mpath() argument
77 nhg = rcu_dereference_raw(nh->nh_grp); in nexthop_free_mpath()
82 nexthop_put(nhge->nh); in nexthop_free_mpath()
91 static void nexthop_free_single(struct nexthop *nh) in nexthop_free_single() argument
95 nhi = rcu_dereference_raw(nh->nh_info); in nexthop_free_single()
98 fib_nh_release(nh->net, &nhi->fib_nh); in nexthop_free_single()
109 struct nexthop *nh = container_of(head, struct nexthop, rcu); in nexthop_free_rcu() local
111 if (nh->is_group) in nexthop_free_rcu()
112 nexthop_free_mpath(nh); in nexthop_free_rcu()
114 nexthop_free_single(nh); in nexthop_free_rcu()
116 kfree(nh); in nexthop_free_rcu()
122 struct nexthop *nh; in nexthop_alloc() local
124 nh = kzalloc(sizeof(struct nexthop), GFP_KERNEL); in nexthop_alloc()
125 if (nh) { in nexthop_alloc()
126 INIT_LIST_HEAD(&nh->fi_list); in nexthop_alloc()
127 INIT_LIST_HEAD(&nh->f6i_list); in nexthop_alloc()
128 INIT_LIST_HEAD(&nh->grp_list); in nexthop_alloc()
129 INIT_LIST_HEAD(&nh->fdb_list); in nexthop_alloc()
131 return nh; in nexthop_alloc()
158 struct nexthop *nh; in nexthop_find_by_id() local
165 nh = rb_entry(parent, struct nexthop, rb_node); in nexthop_find_by_id()
166 if (id < nh->id) in nexthop_find_by_id()
168 else if (id > nh->id) in nexthop_find_by_id()
171 return nh; in nexthop_find_by_id()
213 p->id = nhg->nh_entries[i].nh->id; in nla_put_nh_group()
224 static int nh_fill_node(struct sk_buff *skb, struct nexthop *nh, in nh_fill_node() argument
239 nhm->nh_flags = nh->nh_flags; in nh_fill_node()
240 nhm->nh_protocol = nh->protocol; in nh_fill_node()
244 if (nla_put_u32(skb, NHA_ID, nh->id)) in nh_fill_node()
247 if (nh->is_group) { in nh_fill_node()
248 struct nh_group *nhg = rtnl_dereference(nh->nh_grp); in nh_fill_node()
257 nhi = rtnl_dereference(nh->nh_info); in nh_fill_node()
305 static size_t nh_nlmsg_size_grp(struct nexthop *nh) in nh_nlmsg_size_grp() argument
307 struct nh_group *nhg = rtnl_dereference(nh->nh_grp); in nh_nlmsg_size_grp()
314 static size_t nh_nlmsg_size_single(struct nexthop *nh) in nh_nlmsg_size_single() argument
316 struct nh_info *nhi = rtnl_dereference(nh->nh_info); in nh_nlmsg_size_single()
345 static size_t nh_nlmsg_size(struct nexthop *nh) in nh_nlmsg_size() argument
351 if (nh->is_group) in nh_nlmsg_size()
352 sz += nh_nlmsg_size_grp(nh); in nh_nlmsg_size()
354 sz += nh_nlmsg_size_single(nh); in nh_nlmsg_size()
359 static void nexthop_notify(int event, struct nexthop *nh, struct nl_info *info) in nexthop_notify() argument
366 skb = nlmsg_new(nh_nlmsg_size(nh), gfp_any()); in nexthop_notify()
370 err = nh_fill_node(skb, nh, event, info->portid, seq, nlflags); in nexthop_notify()
386 static bool valid_group_nh(struct nexthop *nh, unsigned int npaths, in valid_group_nh() argument
389 if (nh->is_group) { in valid_group_nh()
390 struct nh_group *nhg = rtnl_dereference(nh->nh_grp); in valid_group_nh()
402 struct nh_info *nhi = rtnl_dereference(nh->nh_info); in valid_group_nh()
415 static int nh_check_attr_fdb_group(struct nexthop *nh, u8 *nh_family, in nh_check_attr_fdb_group() argument
420 nhi = rtnl_dereference(nh->nh_info); in nh_check_attr_fdb_group()
477 struct nexthop *nh; in nh_check_attr_group() local
480 nh = nexthop_find_by_id(net, nhg[i].id); in nh_check_attr_group()
481 if (!nh) { in nh_check_attr_group()
485 if (!valid_group_nh(nh, len, &is_fdb_nh, extack)) in nh_check_attr_group()
488 if (nhg_fdb && nh_check_attr_fdb_group(nh, &nh_family, extack)) in nh_check_attr_group()
509 static bool ipv6_good_nh(const struct fib6_nh *nh) in ipv6_good_nh() argument
516 n = __ipv6_neigh_lookup_noref_stub(nh->fib_nh_dev, &nh->fib_nh_gw6); in ipv6_good_nh()
525 static bool ipv4_good_nh(const struct fib_nh *nh) in ipv4_good_nh() argument
532 n = __ipv4_neigh_lookup_noref(nh->fib_nh_dev, in ipv4_good_nh()
533 (__force u32)nh->fib_nh_gw4); in ipv4_good_nh()
542 struct nexthop *nexthop_select_path(struct nexthop *nh, int hash) in nexthop_select_path() argument
548 if (!nh->is_group) in nexthop_select_path()
549 return nh; in nexthop_select_path()
551 nhg = rcu_dereference(nh->nh_grp); in nexthop_select_path()
559 nhi = rcu_dereference(nhge->nh->nh_info); in nexthop_select_path()
561 return nhge->nh; in nexthop_select_path()
569 return nhge->nh; in nexthop_select_path()
573 return nhge->nh; in nexthop_select_path()
578 rc = nhge->nh; in nexthop_select_path()
585 int nexthop_for_each_fib6_nh(struct nexthop *nh, in nexthop_for_each_fib6_nh() argument
586 int (*cb)(struct fib6_nh *nh, void *arg), in nexthop_for_each_fib6_nh() argument
592 if (nh->is_group) { in nexthop_for_each_fib6_nh()
596 nhg = rcu_dereference_rtnl(nh->nh_grp); in nexthop_for_each_fib6_nh()
600 nhi = rcu_dereference_rtnl(nhge->nh->nh_info); in nexthop_for_each_fib6_nh()
606 nhi = rcu_dereference_rtnl(nh->nh_info); in nexthop_for_each_fib6_nh()
626 int fib6_check_nexthop(struct nexthop *nh, struct fib6_config *cfg, in fib6_check_nexthop() argument
641 if (nh->is_group) { in fib6_check_nexthop()
644 nhg = rtnl_dereference(nh->nh_grp); in fib6_check_nexthop()
649 nhi = rtnl_dereference(nh->nh_info); in fib6_check_nexthop()
707 int fib_check_nexthop(struct nexthop *nh, u8 scope, in fib_check_nexthop() argument
713 if (nh->is_group) { in fib_check_nexthop()
716 nhg = rtnl_dereference(nh->nh_grp); in fib_check_nexthop()
730 nhi = rtnl_dereference(nhg->nh_entries[0].nh->nh_info); in fib_check_nexthop()
733 nhi = rtnl_dereference(nh->nh_info); in fib_check_nexthop()
785 struct nexthop *nh = nhge->nh; in remove_nh_grp_entry() local
789 WARN_ON(!nh); in remove_nh_grp_entry()
812 if (nhg->nh_entries[i].nh == nh) { in remove_nh_grp_entry()
817 nhi = rtnl_dereference(nhges[i].nh->nh_info); in remove_nh_grp_entry()
823 new_nhges[j].nh = nhges[i].nh; in remove_nh_grp_entry()
825 list_add(&new_nhges[j].nh_list, &new_nhges[j].nh->grp_list); in remove_nh_grp_entry()
833 nexthop_put(nhge->nh); in remove_nh_grp_entry()
839 static void remove_nexthop_from_groups(struct net *net, struct nexthop *nh, in remove_nexthop_from_groups() argument
844 list_for_each_entry_safe(nhge, tmp, &nh->grp_list, nh_list) in remove_nexthop_from_groups()
851 static void remove_nexthop_group(struct nexthop *nh, struct nl_info *nlinfo) in remove_nexthop_group() argument
853 struct nh_group *nhg = rcu_dereference_rtnl(nh->nh_grp); in remove_nexthop_group()
859 if (WARN_ON(!nhge->nh)) in remove_nexthop_group()
867 static void __remove_nexthop_fib(struct net *net, struct nexthop *nh) in __remove_nexthop_fib() argument
873 list_for_each_entry(fi, &nh->fi_list, nh_list) { in __remove_nexthop_fib()
881 list_for_each_entry_safe(f6i, tmp, &nh->f6i_list, nh_list) { in __remove_nexthop_fib()
889 static void __remove_nexthop(struct net *net, struct nexthop *nh, in __remove_nexthop() argument
892 __remove_nexthop_fib(net, nh); in __remove_nexthop()
894 if (nh->is_group) { in __remove_nexthop()
895 remove_nexthop_group(nh, nlinfo); in __remove_nexthop()
899 nhi = rtnl_dereference(nh->nh_info); in __remove_nexthop()
903 remove_nexthop_from_groups(net, nh, nlinfo); in __remove_nexthop()
907 static void remove_nexthop(struct net *net, struct nexthop *nh, in remove_nexthop() argument
910 call_nexthop_notifiers(net, NEXTHOP_EVENT_DEL, nh); in remove_nexthop()
913 rb_erase(&nh->rb_node, &net->nexthop.rb_root); in remove_nexthop()
916 nexthop_notify(RTM_DELNEXTHOP, nh, nlinfo); in remove_nexthop()
918 __remove_nexthop(net, nh, nlinfo); in remove_nexthop()
921 nexthop_put(nh); in remove_nexthop()
927 static void nh_rt_cache_flush(struct net *net, struct nexthop *nh, in nh_rt_cache_flush() argument
934 if (!list_empty(&nh->fi_list)) in nh_rt_cache_flush()
937 list_for_each_entry(f6i, &nh->f6i_list, nh_list) in nh_rt_cache_flush()
952 struct nh_info *nhi = rtnl_dereference(nhge->nh->nh_info); in nh_rt_cache_flush()
998 nhi = rtnl_dereference(nhges[i].nh->nh_info); in nh_group_v4_update()
1046 static void __nexthop_replace_notify(struct net *net, struct nexthop *nh, in __nexthop_replace_notify() argument
1051 if (!list_empty(&nh->fi_list)) { in __nexthop_replace_notify()
1058 list_for_each_entry(fi, &nh->fi_list, nh_list) in __nexthop_replace_notify()
1063 list_for_each_entry(fi, &nh->fi_list, nh_list) in __nexthop_replace_notify()
1067 list_for_each_entry(f6i, &nh->f6i_list, nh_list) in __nexthop_replace_notify()
1075 static void nexthop_replace_notify(struct net *net, struct nexthop *nh, in nexthop_replace_notify() argument
1080 __nexthop_replace_notify(net, nh, info); in nexthop_replace_notify()
1082 list_for_each_entry(nhge, &nh->grp_list, nh_list) in nexthop_replace_notify()
1158 struct nexthop *nh; in insert_nexthop() local
1166 nh = rb_entry(parent, struct nexthop, rb_node); in insert_nexthop()
1167 if (new_id < nh->id) { in insert_nexthop()
1169 } else if (new_id > nh->id) { in insert_nexthop()
1172 rc = replace_nexthop(net, nh, new_nh, extack); in insert_nexthop()
1174 new_nh = nh; /* send notification with old nh */ in insert_nexthop()
1232 struct nexthop *nh; in flush_all_nexthops() local
1235 nh = rb_entry(node, struct nexthop, rb_node); in flush_all_nexthops()
1236 remove_nexthop(net, nh, NULL); in flush_all_nexthops()
1248 struct nexthop *nh; in nexthop_create_group() local
1254 nh = nexthop_alloc(); in nexthop_create_group()
1255 if (!nh) in nexthop_create_group()
1258 nh->is_group = 1; in nexthop_create_group()
1262 kfree(nh); in nexthop_create_group()
1270 kfree(nh); in nexthop_create_group()
1287 nhg->nh_entries[i].nh = nhe; in nexthop_create_group()
1290 nhg->nh_entries[i].nh_parent = nh; in nexthop_create_group()
1301 rcu_assign_pointer(nh->nh_grp, nhg); in nexthop_create_group()
1303 return nh; in nexthop_create_group()
1308 nexthop_put(nhg->nh_entries[i].nh); in nexthop_create_group()
1313 kfree(nh); in nexthop_create_group()
1318 static int nh_create_ipv4(struct net *net, struct nexthop *nh, in nh_create_ipv4() argument
1347 nh->nh_flags = fib_nh->fib_nh_flags; in nh_create_ipv4()
1357 static int nh_create_ipv6(struct net *net, struct nexthop *nh, in nh_create_ipv6() argument
1386 nh->nh_flags = fib6_nh->fib_nh_flags; in nh_create_ipv6()
1396 struct nexthop *nh; in nexthop_create() local
1399 nh = nexthop_alloc(); in nexthop_create()
1400 if (!nh) in nexthop_create()
1405 kfree(nh); in nexthop_create()
1409 nh->nh_flags = cfg->nh_flags; in nexthop_create()
1410 nh->net = net; in nexthop_create()
1412 nhi->nh_parent = nh; in nexthop_create()
1426 err = nh_create_ipv4(net, nh, nhi, cfg, extack); in nexthop_create()
1429 err = nh_create_ipv6(net, nh, nhi, cfg, extack); in nexthop_create()
1435 kfree(nh); in nexthop_create()
1443 rcu_assign_pointer(nh->nh_info, nhi); in nexthop_create()
1445 return nh; in nexthop_create()
1452 struct nexthop *nh; in nexthop_add() local
1469 nh = nexthop_create_group(net, cfg); in nexthop_add()
1471 nh = nexthop_create(net, cfg, extack); in nexthop_add()
1473 if (IS_ERR(nh)) in nexthop_add()
1474 return nh; in nexthop_add()
1476 refcount_set(&nh->refcnt, 1); in nexthop_add()
1477 nh->id = cfg->nh_id; in nexthop_add()
1478 nh->protocol = cfg->nh_protocol; in nexthop_add()
1479 nh->net = net; in nexthop_add()
1481 err = insert_nexthop(net, nh, cfg, extack); in nexthop_add()
1483 __remove_nexthop(net, nh, NULL); in nexthop_add()
1484 nexthop_put(nh); in nexthop_add()
1485 nh = ERR_PTR(err); in nexthop_add()
1488 return nh; in nexthop_add()
1678 struct nexthop *nh; in rtm_new_nexthop() local
1683 nh = nexthop_add(net, &cfg, extack); in rtm_new_nexthop()
1684 if (IS_ERR(nh)) in rtm_new_nexthop()
1685 err = PTR_ERR(nh); in rtm_new_nexthop()
1746 struct nexthop *nh; in rtm_del_nexthop() local
1754 nh = nexthop_find_by_id(net, id); in rtm_del_nexthop()
1755 if (!nh) in rtm_del_nexthop()
1758 remove_nexthop(net, nh, &nlinfo); in rtm_del_nexthop()
1769 struct nexthop *nh; in rtm_get_nexthop() local
1783 nh = nexthop_find_by_id(net, id); in rtm_get_nexthop()
1784 if (!nh) in rtm_get_nexthop()
1787 err = nh_fill_node(skb, nh, RTM_NEWNEXTHOP, NETLINK_CB(in_skb).portid, in rtm_get_nexthop()
1802 static bool nh_dump_filtered(struct nexthop *nh, int dev_idx, int master_idx, in nh_dump_filtered() argument
1808 if (group_filter && !nh->is_group) in nh_dump_filtered()
1814 if (nh->is_group) in nh_dump_filtered()
1817 nhi = rtnl_dereference(nh->nh_info); in nh_dump_filtered()
1915 struct nexthop *nh; in rtm_dump_nexthop() local
1920 nh = rb_entry(node, struct nexthop, rb_node); in rtm_dump_nexthop()
1921 if (nh_dump_filtered(nh, dev_filter_idx, master_idx, in rtm_dump_nexthop()
1925 err = nh_fill_node(skb, nh, RTM_NEWNEXTHOP, in rtm_dump_nexthop()