File Index
Files and directories
Sign in
FILE

nexthop.c

File preview with syntax highlighting.

linux-6.19.14/net/ipv4/nexthop.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/* Generic nexthop implementation
   3 *
   4 * Copyright (c) 2017-19 Cumulus Networks
   5 * Copyright (c) 2017-19 David Ahern <dsa@cumulusnetworks.com>
   6 */
   7
   8#include <linux/nexthop.h>
   9#include <linux/rtnetlink.h>
  10#include <linux/slab.h>
  11#include <linux/vmalloc.h>
  12#include <net/arp.h>
  13#include <net/ipv6_stubs.h>
  14#include <net/lwtunnel.h>
  15#include <net/ndisc.h>
  16#include <net/nexthop.h>
  17#include <net/route.h>
  18#include <net/sock.h>
  19
  20#define NH_RES_DEFAULT_IDLE_TIMER	(120 * HZ)
  21#define NH_RES_DEFAULT_UNBALANCED_TIMER	0	/* No forced rebalancing. */
  22
  23static void remove_nexthop(struct net *net, struct nexthop *nh,
  24			   struct nl_info *nlinfo);
  25
  26#define NH_DEV_HASHBITS  8
  27#define NH_DEV_HASHSIZE (1U << NH_DEV_HASHBITS)
  28
  29#define NHA_OP_FLAGS_DUMP_ALL (NHA_OP_FLAG_DUMP_STATS |		\
  30			       NHA_OP_FLAG_DUMP_HW_STATS)
  31
  32static const struct nla_policy rtm_nh_policy_new[] = {
  33	[NHA_ID]		= { .type = NLA_U32 },
  34	[NHA_GROUP]		= { .type = NLA_BINARY },
  35	[NHA_GROUP_TYPE]	= { .type = NLA_U16 },
  36	[NHA_BLACKHOLE]		= { .type = NLA_FLAG },
  37	[NHA_OIF]		= { .type = NLA_U32 },
  38	[NHA_GATEWAY]		= { .type = NLA_BINARY },
  39	[NHA_ENCAP_TYPE]	= { .type = NLA_U16 },
  40	[NHA_ENCAP]		= { .type = NLA_NESTED },
  41	[NHA_FDB]		= { .type = NLA_FLAG },
  42	[NHA_RES_GROUP]		= { .type = NLA_NESTED },
  43	[NHA_HW_STATS_ENABLE]	= NLA_POLICY_MAX(NLA_U32, true),
  44};
  45
  46static const struct nla_policy rtm_nh_policy_get[] = {
  47	[NHA_ID]		= { .type = NLA_U32 },
  48	[NHA_OP_FLAGS]		= NLA_POLICY_MASK(NLA_U32,
  49						  NHA_OP_FLAGS_DUMP_ALL),
  50};
  51
  52static const struct nla_policy rtm_nh_policy_del[] = {
  53	[NHA_ID]		= { .type = NLA_U32 },
  54};
  55
  56static const struct nla_policy rtm_nh_policy_dump[] = {
  57	[NHA_OIF]		= { .type = NLA_U32 },
  58	[NHA_GROUPS]		= { .type = NLA_FLAG },
  59	[NHA_MASTER]		= { .type = NLA_U32 },
  60	[NHA_FDB]		= { .type = NLA_FLAG },
  61	[NHA_OP_FLAGS]		= NLA_POLICY_MASK(NLA_U32,
  62						  NHA_OP_FLAGS_DUMP_ALL),
  63};
  64
  65static const struct nla_policy rtm_nh_res_policy_new[] = {
  66	[NHA_RES_GROUP_BUCKETS]			= { .type = NLA_U16 },
  67	[NHA_RES_GROUP_IDLE_TIMER]		= { .type = NLA_U32 },
  68	[NHA_RES_GROUP_UNBALANCED_TIMER]	= { .type = NLA_U32 },
  69};
  70
  71static const struct nla_policy rtm_nh_policy_dump_bucket[] = {
  72	[NHA_ID]		= { .type = NLA_U32 },
  73	[NHA_OIF]		= { .type = NLA_U32 },
  74	[NHA_MASTER]		= { .type = NLA_U32 },
  75	[NHA_RES_BUCKET]	= { .type = NLA_NESTED },
  76};
  77
  78static const struct nla_policy rtm_nh_res_bucket_policy_dump[] = {
  79	[NHA_RES_BUCKET_NH_ID]	= { .type = NLA_U32 },
  80};
  81
  82static const struct nla_policy rtm_nh_policy_get_bucket[] = {
  83	[NHA_ID]		= { .type = NLA_U32 },
  84	[NHA_RES_BUCKET]	= { .type = NLA_NESTED },
  85};
  86
  87static const struct nla_policy rtm_nh_res_bucket_policy_get[] = {
  88	[NHA_RES_BUCKET_INDEX]	= { .type = NLA_U16 },
  89};
  90
  91static bool nexthop_notifiers_is_empty(struct net *net)
  92{
  93	return !net->nexthop.notifier_chain.head;
  94}
  95
  96static void
  97__nh_notifier_single_info_init(struct nh_notifier_single_info *nh_info,
  98			       const struct nh_info *nhi)
  99{
 100	nh_info->dev = nhi->fib_nhc.nhc_dev;
 101	nh_info->gw_family = nhi->fib_nhc.nhc_gw_family;
 102	if (nh_info->gw_family == AF_INET)
 103		nh_info->ipv4 = nhi->fib_nhc.nhc_gw.ipv4;
 104	else if (nh_info->gw_family == AF_INET6)
 105		nh_info->ipv6 = nhi->fib_nhc.nhc_gw.ipv6;
 106
 107	nh_info->id = nhi->nh_parent->id;
 108	nh_info->is_reject = nhi->reject_nh;
 109	nh_info->is_fdb = nhi->fdb_nh;
 110	nh_info->has_encap = !!nhi->fib_nhc.nhc_lwtstate;
 111}
 112
 113static int nh_notifier_single_info_init(struct nh_notifier_info *info,
 114					const struct nexthop *nh)
 115{
 116	struct nh_info *nhi = rtnl_dereference(nh->nh_info);
 117
 118	info->type = NH_NOTIFIER_INFO_TYPE_SINGLE;
 119	info->nh = kzalloc(sizeof(*info->nh), GFP_KERNEL);
 120	if (!info->nh)
 121		return -ENOMEM;
 122
 123	__nh_notifier_single_info_init(info->nh, nhi);
 124
 125	return 0;
 126}
 127
 128static void nh_notifier_single_info_fini(struct nh_notifier_info *info)
 129{
 130	kfree(info->nh);
 131}
 132
 133static int nh_notifier_mpath_info_init(struct nh_notifier_info *info,
 134				       struct nh_group *nhg)
 135{
 136	u16 num_nh = nhg->num_nh;
 137	int i;
 138
 139	info->type = NH_NOTIFIER_INFO_TYPE_GRP;
 140	info->nh_grp = kzalloc(struct_size(info->nh_grp, nh_entries, num_nh),
 141			       GFP_KERNEL);
 142	if (!info->nh_grp)
 143		return -ENOMEM;
 144
 145	info->nh_grp->num_nh = num_nh;
 146	info->nh_grp->is_fdb = nhg->fdb_nh;
 147	info->nh_grp->hw_stats = nhg->hw_stats;
 148
 149	for (i = 0; i < num_nh; i++) {
 150		struct nh_grp_entry *nhge = &nhg->nh_entries[i];
 151		struct nh_info *nhi;
 152
 153		nhi = rtnl_dereference(nhge->nh->nh_info);
 154		info->nh_grp->nh_entries[i].weight = nhge->weight;
 155		__nh_notifier_single_info_init(&info->nh_grp->nh_entries[i].nh,
 156					       nhi);
 157	}
 158
 159	return 0;
 160}
 161
 162static int nh_notifier_res_table_info_init(struct nh_notifier_info *info,
 163					   struct nh_group *nhg)
 164{
 165	struct nh_res_table *res_table = rtnl_dereference(nhg->res_table);
 166	u16 num_nh_buckets = res_table->num_nh_buckets;
 167	unsigned long size;
 168	u16 i;
 169
 170	info->type = NH_NOTIFIER_INFO_TYPE_RES_TABLE;
 171	size = struct_size(info->nh_res_table, nhs, num_nh_buckets);
 172	info->nh_res_table = __vmalloc(size, GFP_KERNEL | __GFP_ZERO |
 173				       __GFP_NOWARN);
 174	if (!info->nh_res_table)
 175		return -ENOMEM;
 176
 177	info->nh_res_table->num_nh_buckets = num_nh_buckets;
 178	info->nh_res_table->hw_stats = nhg->hw_stats;
 179
 180	for (i = 0; i < num_nh_buckets; i++) {
 181		struct nh_res_bucket *bucket = &res_table->nh_buckets[i];
 182		struct nh_grp_entry *nhge;
 183		struct nh_info *nhi;
 184
 185		nhge = rtnl_dereference(bucket->nh_entry);
 186		nhi = rtnl_dereference(nhge->nh->nh_info);
 187		__nh_notifier_single_info_init(&info->nh_res_table->nhs[i],
 188					       nhi);
 189	}
 190
 191	return 0;
 192}
 193
 194static int nh_notifier_grp_info_init(struct nh_notifier_info *info,
 195				     const struct nexthop *nh)
 196{
 197	struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
 198
 199	if (nhg->hash_threshold)
 200		return nh_notifier_mpath_info_init(info, nhg);
 201	else if (nhg->resilient)
 202		return nh_notifier_res_table_info_init(info, nhg);
 203	return -EINVAL;
 204}
 205
 206static void nh_notifier_grp_info_fini(struct nh_notifier_info *info,
 207				      const struct nexthop *nh)
 208{
 209	struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
 210
 211	if (nhg->hash_threshold)
 212		kfree(info->nh_grp);
 213	else if (nhg->resilient)
 214		vfree(info->nh_res_table);
 215}
 216
 217static int nh_notifier_info_init(struct nh_notifier_info *info,
 218				 const struct nexthop *nh)
 219{
 220	info->id = nh->id;
 221
 222	if (nh->is_group)
 223		return nh_notifier_grp_info_init(info, nh);
 224	else
 225		return nh_notifier_single_info_init(info, nh);
 226}
 227
 228static void nh_notifier_info_fini(struct nh_notifier_info *info,
 229				  const struct nexthop *nh)
 230{
 231	if (nh->is_group)
 232		nh_notifier_grp_info_fini(info, nh);
 233	else
 234		nh_notifier_single_info_fini(info);
 235}
 236
 237static int call_nexthop_notifiers(struct net *net,
 238				  enum nexthop_event_type event_type,
 239				  struct nexthop *nh,
 240				  struct netlink_ext_ack *extack)
 241{
 242	struct nh_notifier_info info = {
 243		.net = net,
 244		.extack = extack,
 245	};
 246	int err;
 247
 248	ASSERT_RTNL();
 249
 250	if (nexthop_notifiers_is_empty(net))
 251		return 0;
 252
 253	err = nh_notifier_info_init(&info, nh);
 254	if (err) {
 255		NL_SET_ERR_MSG(extack, "Failed to initialize nexthop notifier info");
 256		return err;
 257	}
 258
 259	err = blocking_notifier_call_chain(&net->nexthop.notifier_chain,
 260					   event_type, &info);
 261	nh_notifier_info_fini(&info, nh);
 262
 263	return notifier_to_errno(err);
 264}
 265
 266static int
 267nh_notifier_res_bucket_idle_timer_get(const struct nh_notifier_info *info,
 268				      bool force, unsigned int *p_idle_timer_ms)
 269{
 270	struct nh_res_table *res_table;
 271	struct nh_group *nhg;
 272	struct nexthop *nh;
 273	int err = 0;
 274
 275	/* When 'force' is false, nexthop bucket replacement is performed
 276	 * because the bucket was deemed to be idle. In this case, capable
 277	 * listeners can choose to perform an atomic replacement: The bucket is
 278	 * only replaced if it is inactive. However, if the idle timer interval
 279	 * is smaller than the interval in which a listener is querying
 280	 * buckets' activity from the device, then atomic replacement should
 281	 * not be tried. Pass the idle timer value to listeners, so that they
 282	 * could determine which type of replacement to perform.
 283	 */
 284	if (force) {
 285		*p_idle_timer_ms = 0;
 286		return 0;
 287	}
 288
 289	rcu_read_lock();
 290
 291	nh = nexthop_find_by_id(info->net, info->id);
 292	if (!nh) {
 293		err = -EINVAL;
 294		goto out;
 295	}
 296
 297	nhg = rcu_dereference(nh->nh_grp);
 298	res_table = rcu_dereference(nhg->res_table);
 299	*p_idle_timer_ms = jiffies_to_msecs(res_table->idle_timer);
 300
 301out:
 302	rcu_read_unlock();
 303
 304	return err;
 305}
 306
 307static int nh_notifier_res_bucket_info_init(struct nh_notifier_info *info,
 308					    u16 bucket_index, bool force,
 309					    struct nh_info *oldi,
 310					    struct nh_info *newi)
 311{
 312	unsigned int idle_timer_ms;
 313	int err;
 314
 315	err = nh_notifier_res_bucket_idle_timer_get(info, force,
 316						    &idle_timer_ms);
 317	if (err)
 318		return err;
 319
 320	info->type = NH_NOTIFIER_INFO_TYPE_RES_BUCKET;
 321	info->nh_res_bucket = kzalloc(sizeof(*info->nh_res_bucket),
 322				      GFP_KERNEL);
 323	if (!info->nh_res_bucket)
 324		return -ENOMEM;
 325
 326	info->nh_res_bucket->bucket_index = bucket_index;
 327	info->nh_res_bucket->idle_timer_ms = idle_timer_ms;
 328	info->nh_res_bucket->force = force;
 329	__nh_notifier_single_info_init(&info->nh_res_bucket->old_nh, oldi);
 330	__nh_notifier_single_info_init(&info->nh_res_bucket->new_nh, newi);
 331	return 0;
 332}
 333
 334static void nh_notifier_res_bucket_info_fini(struct nh_notifier_info *info)
 335{
 336	kfree(info->nh_res_bucket);
 337}
 338
 339static int __call_nexthop_res_bucket_notifiers(struct net *net, u32 nhg_id,
 340					       u16 bucket_index, bool force,
 341					       struct nh_info *oldi,
 342					       struct nh_info *newi,
 343					       struct netlink_ext_ack *extack)
 344{
 345	struct nh_notifier_info info = {
 346		.net = net,
 347		.extack = extack,
 348		.id = nhg_id,
 349	};
 350	int err;
 351
 352	if (nexthop_notifiers_is_empty(net))
 353		return 0;
 354
 355	err = nh_notifier_res_bucket_info_init(&info, bucket_index, force,
 356					       oldi, newi);
 357	if (err)
 358		return err;
 359
 360	err = blocking_notifier_call_chain(&net->nexthop.notifier_chain,
 361					   NEXTHOP_EVENT_BUCKET_REPLACE, &info);
 362	nh_notifier_res_bucket_info_fini(&info);
 363
 364	return notifier_to_errno(err);
 365}
 366
 367/* There are three users of RES_TABLE, and NHs etc. referenced from there:
 368 *
 369 * 1) a collection of callbacks for NH maintenance. This operates under
 370 *    RTNL,
 371 * 2) the delayed work that gradually balances the resilient table,
 372 * 3) and nexthop_select_path(), operating under RCU.
 373 *
 374 * Both the delayed work and the RTNL block are writers, and need to
 375 * maintain mutual exclusion. Since there are only two and well-known
 376 * writers for each table, the RTNL code can make sure it has exclusive
 377 * access thus:
 378 *
 379 * - Have the DW operate without locking;
 380 * - synchronously cancel the DW;
 381 * - do the writing;
 382 * - if the write was not actually a delete, call upkeep, which schedules
 383 *   DW again if necessary.
 384 *
 385 * The functions that are always called from the RTNL context use
 386 * rtnl_dereference(). The functions that can also be called from the DW do
 387 * a raw dereference and rely on the above mutual exclusion scheme.
 388 */
 389#define nh_res_dereference(p) (rcu_dereference_raw(p))
 390
 391static int call_nexthop_res_bucket_notifiers(struct net *net, u32 nhg_id,
 392					     u16 bucket_index, bool force,
 393					     struct nexthop *old_nh,
 394					     struct nexthop *new_nh,
 395					     struct netlink_ext_ack *extack)
 396{
 397	struct nh_info *oldi = nh_res_dereference(old_nh->nh_info);
 398	struct nh_info *newi = nh_res_dereference(new_nh->nh_info);
 399
 400	return __call_nexthop_res_bucket_notifiers(net, nhg_id, bucket_index,
 401						   force, oldi, newi, extack);
 402}
 403
 404static int call_nexthop_res_table_notifiers(struct net *net, struct nexthop *nh,
 405					    struct netlink_ext_ack *extack)
 406{
 407	struct nh_notifier_info info = {
 408		.net = net,
 409		.extack = extack,
 410		.id = nh->id,
 411	};
 412	struct nh_group *nhg;
 413	int err;
 414
 415	ASSERT_RTNL();
 416
 417	if (nexthop_notifiers_is_empty(net))
 418		return 0;
 419
 420	/* At this point, the nexthop buckets are still not populated. Only
 421	 * emit a notification with the logical nexthops, so that a listener
 422	 * could potentially veto it in case of unsupported configuration.
 423	 */
 424	nhg = rtnl_dereference(nh->nh_grp);
 425	err = nh_notifier_mpath_info_init(&info, nhg);
 426	if (err) {
 427		NL_SET_ERR_MSG(extack, "Failed to initialize nexthop notifier info");
 428		return err;
 429	}
 430
 431	err = blocking_notifier_call_chain(&net->nexthop.notifier_chain,
 432					   NEXTHOP_EVENT_RES_TABLE_PRE_REPLACE,
 433					   &info);
 434	kfree(info.nh_grp);
 435
 436	return notifier_to_errno(err);
 437}
 438
 439static int call_nexthop_notifier(struct notifier_block *nb, struct net *net,
 440				 enum nexthop_event_type event_type,
 441				 struct nexthop *nh,
 442				 struct netlink_ext_ack *extack)
 443{
 444	struct nh_notifier_info info = {
 445		.net = net,
 446		.extack = extack,
 447	};
 448	int err;
 449
 450	err = nh_notifier_info_init(&info, nh);
 451	if (err)
 452		return err;
 453
 454	err = nb->notifier_call(nb, event_type, &info);
 455	nh_notifier_info_fini(&info, nh);
 456
 457	return notifier_to_errno(err);
 458}
 459
 460static unsigned int nh_dev_hashfn(unsigned int val)
 461{
 462	unsigned int mask = NH_DEV_HASHSIZE - 1;
 463
 464	return (val ^
 465		(val >> NH_DEV_HASHBITS) ^
 466		(val >> (NH_DEV_HASHBITS * 2))) & mask;
 467}
 468
 469static void nexthop_devhash_add(struct net *net, struct nh_info *nhi)
 470{
 471	struct net_device *dev = nhi->fib_nhc.nhc_dev;
 472	struct hlist_head *head;
 473	unsigned int hash;
 474
 475	WARN_ON(!dev);
 476
 477	hash = nh_dev_hashfn(dev->ifindex);
 478	head = &net->nexthop.devhash[hash];
 479	hlist_add_head(&nhi->dev_hash, head);
 480}
 481
 482static void nexthop_free_group(struct nexthop *nh)
 483{
 484	struct nh_group *nhg;
 485	int i;
 486
 487	nhg = rcu_dereference_raw(nh->nh_grp);
 488	for (i = 0; i < nhg->num_nh; ++i) {
 489		struct nh_grp_entry *nhge = &nhg->nh_entries[i];
 490
 491		WARN_ON(!list_empty(&nhge->nh_list));
 492		free_percpu(nhge->stats);
 493		nexthop_put(nhge->nh);
 494	}
 495
 496	WARN_ON(nhg->spare == nhg);
 497
 498	if (nhg->resilient)
 499		vfree(rcu_dereference_raw(nhg->res_table));
 500
 501	kfree(nhg->spare);
 502	kfree(nhg);
 503}
 504
 505static void nexthop_free_single(struct nexthop *nh)
 506{
 507	struct nh_info *nhi;
 508
 509	nhi = rcu_dereference_raw(nh->nh_info);
 510	switch (nhi->family) {
 511	case AF_INET:
 512		fib_nh_release(nh->net, &nhi->fib_nh);
 513		break;
 514	case AF_INET6:
 515		ipv6_stub->fib6_nh_release(&nhi->fib6_nh);
 516		break;
 517	}
 518	kfree(nhi);
 519}
 520
 521void nexthop_free_rcu(struct rcu_head *head)
 522{
 523	struct nexthop *nh = container_of(head, struct nexthop, rcu);
 524
 525	if (nh->is_group)
 526		nexthop_free_group(nh);
 527	else
 528		nexthop_free_single(nh);
 529
 530	kfree(nh);
 531}
 532EXPORT_SYMBOL_GPL(nexthop_free_rcu);
 533
 534static struct nexthop *nexthop_alloc(void)
 535{
 536	struct nexthop *nh;
 537
 538	nh = kzalloc(sizeof(struct nexthop), GFP_KERNEL);
 539	if (nh) {
 540		INIT_LIST_HEAD(&nh->fi_list);
 541		INIT_LIST_HEAD(&nh->f6i_list);
 542		INIT_LIST_HEAD(&nh->grp_list);
 543		INIT_LIST_HEAD(&nh->fdb_list);
 544		spin_lock_init(&nh->lock);
 545	}
 546	return nh;
 547}
 548
 549static struct nh_group *nexthop_grp_alloc(u16 num_nh)
 550{
 551	struct nh_group *nhg;
 552
 553	nhg = kzalloc(struct_size(nhg, nh_entries, num_nh), GFP_KERNEL);
 554	if (nhg)
 555		nhg->num_nh = num_nh;
 556
 557	return nhg;
 558}
 559
 560static void nh_res_table_upkeep_dw(struct work_struct *work);
 561
 562static struct nh_res_table *
 563nexthop_res_table_alloc(struct net *net, u32 nhg_id, struct nh_config *cfg)
 564{
 565	const u16 num_nh_buckets = cfg->nh_grp_res_num_buckets;
 566	struct nh_res_table *res_table;
 567	unsigned long size;
 568
 569	size = struct_size(res_table, nh_buckets, num_nh_buckets);
 570	res_table = __vmalloc(size, GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN);
 571	if (!res_table)
 572		return NULL;
 573
 574	res_table->net = net;
 575	res_table->nhg_id = nhg_id;
 576	INIT_DELAYED_WORK(&res_table->upkeep_dw, &nh_res_table_upkeep_dw);
 577	INIT_LIST_HEAD(&res_table->uw_nh_entries);
 578	res_table->idle_timer = cfg->nh_grp_res_idle_timer;
 579	res_table->unbalanced_timer = cfg->nh_grp_res_unbalanced_timer;
 580	res_table->num_nh_buckets = num_nh_buckets;
 581	return res_table;
 582}
 583
 584static void nh_base_seq_inc(struct net *net)
 585{
 586	while (++net->nexthop.seq == 0)
 587		;
 588}
 589
 590/* no reference taken; rcu lock or rtnl must be held */
 591struct nexthop *nexthop_find_by_id(struct net *net, u32 id)
 592{
 593	struct rb_node **pp, *parent = NULL, *next;
 594
 595	pp = &net->nexthop.rb_root.rb_node;
 596	while (1) {
 597		struct nexthop *nh;
 598
 599		next = rcu_dereference_raw(*pp);
 600		if (!next)
 601			break;
 602		parent = next;
 603
 604		nh = rb_entry(parent, struct nexthop, rb_node);
 605		if (id < nh->id)
 606			pp = &next->rb_left;
 607		else if (id > nh->id)
 608			pp = &next->rb_right;
 609		else
 610			return nh;
 611	}
 612	return NULL;
 613}
 614EXPORT_SYMBOL_GPL(nexthop_find_by_id);
 615
 616/* used for auto id allocation; called with rtnl held */
 617static u32 nh_find_unused_id(struct net *net)
 618{
 619	u32 id_start = net->nexthop.last_id_allocated;
 620
 621	while (1) {
 622		net->nexthop.last_id_allocated++;
 623		if (net->nexthop.last_id_allocated == id_start)
 624			break;
 625
 626		if (!nexthop_find_by_id(net, net->nexthop.last_id_allocated))
 627			return net->nexthop.last_id_allocated;
 628	}
 629	return 0;
 630}
 631
 632static void nh_res_time_set_deadline(unsigned long next_time,
 633				     unsigned long *deadline)
 634{
 635	if (time_before(next_time, *deadline))
 636		*deadline = next_time;
 637}
 638
 639static clock_t nh_res_table_unbalanced_time(struct nh_res_table *res_table)
 640{
 641	if (list_empty(&res_table->uw_nh_entries))
 642		return 0;
 643	return jiffies_delta_to_clock_t(jiffies - res_table->unbalanced_since);
 644}
 645
 646static int nla_put_nh_group_res(struct sk_buff *skb, struct nh_group *nhg)
 647{
 648	struct nh_res_table *res_table = rtnl_dereference(nhg->res_table);
 649	struct nlattr *nest;
 650
 651	nest = nla_nest_start(skb, NHA_RES_GROUP);
 652	if (!nest)
 653		return -EMSGSIZE;
 654
 655	if (nla_put_u16(skb, NHA_RES_GROUP_BUCKETS,
 656			res_table->num_nh_buckets) ||
 657	    nla_put_u32(skb, NHA_RES_GROUP_IDLE_TIMER,
 658			jiffies_to_clock_t(res_table->idle_timer)) ||
 659	    nla_put_u32(skb, NHA_RES_GROUP_UNBALANCED_TIMER,
 660			jiffies_to_clock_t(res_table->unbalanced_timer)) ||
 661	    nla_put_u64_64bit(skb, NHA_RES_GROUP_UNBALANCED_TIME,
 662			      nh_res_table_unbalanced_time(res_table),
 663			      NHA_RES_GROUP_PAD))
 664		goto nla_put_failure;
 665
 666	nla_nest_end(skb, nest);
 667	return 0;
 668
 669nla_put_failure:
 670	nla_nest_cancel(skb, nest);
 671	return -EMSGSIZE;
 672}
 673
 674static void nh_grp_entry_stats_inc(struct nh_grp_entry *nhge)
 675{
 676	struct nh_grp_entry_stats *cpu_stats;
 677
 678	cpu_stats = get_cpu_ptr(nhge->stats);
 679	u64_stats_update_begin(&cpu_stats->syncp);
 680	u64_stats_inc(&cpu_stats->packets);
 681	u64_stats_update_end(&cpu_stats->syncp);
 682	put_cpu_ptr(cpu_stats);
 683}
 684
 685static void nh_grp_entry_stats_read(struct nh_grp_entry *nhge,
 686				    u64 *ret_packets)
 687{
 688	int i;
 689
 690	*ret_packets = 0;
 691
 692	for_each_possible_cpu(i) {
 693		struct nh_grp_entry_stats *cpu_stats;
 694		unsigned int start;
 695		u64 packets;
 696
 697		cpu_stats = per_cpu_ptr(nhge->stats, i);
 698		do {
 699			start = u64_stats_fetch_begin(&cpu_stats->syncp);
 700			packets = u64_stats_read(&cpu_stats->packets);
 701		} while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
 702
 703		*ret_packets += packets;
 704	}
 705}
 706
 707static int nh_notifier_grp_hw_stats_init(struct nh_notifier_info *info,
 708					 const struct nexthop *nh)
 709{
 710	struct nh_group *nhg;
 711	int i;
 712
 713	ASSERT_RTNL();
 714	nhg = rtnl_dereference(nh->nh_grp);
 715
 716	info->id = nh->id;
 717	info->type = NH_NOTIFIER_INFO_TYPE_GRP_HW_STATS;
 718	info->nh_grp_hw_stats = kzalloc(struct_size(info->nh_grp_hw_stats,
 719						    stats, nhg->num_nh),
 720					GFP_KERNEL);
 721	if (!info->nh_grp_hw_stats)
 722		return -ENOMEM;
 723
 724	info->nh_grp_hw_stats->num_nh = nhg->num_nh;
 725	for (i = 0; i < nhg->num_nh; i++) {
 726		struct nh_grp_entry *nhge = &nhg->nh_entries[i];
 727
 728		info->nh_grp_hw_stats->stats[i].id = nhge->nh->id;
 729	}
 730
 731	return 0;
 732}
 733
 734static void nh_notifier_grp_hw_stats_fini(struct nh_notifier_info *info)
 735{
 736	kfree(info->nh_grp_hw_stats);
 737}
 738
 739void nh_grp_hw_stats_report_delta(struct nh_notifier_grp_hw_stats_info *info,
 740				  unsigned int nh_idx,
 741				  u64 delta_packets)
 742{
 743	info->hw_stats_used = true;
 744	info->stats[nh_idx].packets += delta_packets;
 745}
 746EXPORT_SYMBOL(nh_grp_hw_stats_report_delta);
 747
 748static void nh_grp_hw_stats_apply_update(struct nexthop *nh,
 749					 struct nh_notifier_info *info)
 750{
 751	struct nh_group *nhg;
 752	int i;
 753
 754	ASSERT_RTNL();
 755	nhg = rtnl_dereference(nh->nh_grp);
 756
 757	for (i = 0; i < nhg->num_nh; i++) {
 758		struct nh_grp_entry *nhge = &nhg->nh_entries[i];
 759
 760		nhge->packets_hw += info->nh_grp_hw_stats->stats[i].packets;
 761	}
 762}
 763
 764static int nh_grp_hw_stats_update(struct nexthop *nh, bool *hw_stats_used)
 765{
 766	struct nh_notifier_info info = {
 767		.net = nh->net,
 768	};
 769	struct net *net = nh->net;
 770	int err;
 771
 772	if (nexthop_notifiers_is_empty(net)) {
 773		*hw_stats_used = false;
 774		return 0;
 775	}
 776
 777	err = nh_notifier_grp_hw_stats_init(&info, nh);
 778	if (err)
 779		return err;
 780
 781	err = blocking_notifier_call_chain(&net->nexthop.notifier_chain,
 782					   NEXTHOP_EVENT_HW_STATS_REPORT_DELTA,
 783					   &info);
 784
 785	/* Cache whatever we got, even if there was an error, otherwise the
 786	 * successful stats retrievals would get lost.
 787	 */
 788	nh_grp_hw_stats_apply_update(nh, &info);
 789	*hw_stats_used = info.nh_grp_hw_stats->hw_stats_used;
 790
 791	nh_notifier_grp_hw_stats_fini(&info);
 792	return notifier_to_errno(err);
 793}
 794
 795static int nla_put_nh_group_stats_entry(struct sk_buff *skb,
 796					struct nh_grp_entry *nhge,
 797					u32 op_flags)
 798{
 799	struct nlattr *nest;
 800	u64 packets;
 801
 802	nh_grp_entry_stats_read(nhge, &packets);
 803
 804	nest = nla_nest_start(skb, NHA_GROUP_STATS_ENTRY);
 805	if (!nest)
 806		return -EMSGSIZE;
 807
 808	if (nla_put_u32(skb, NHA_GROUP_STATS_ENTRY_ID, nhge->nh->id) ||
 809	    nla_put_uint(skb, NHA_GROUP_STATS_ENTRY_PACKETS,
 810			 packets + nhge->packets_hw))
 811		goto nla_put_failure;
 812
 813	if (op_flags & NHA_OP_FLAG_DUMP_HW_STATS &&
 814	    nla_put_uint(skb, NHA_GROUP_STATS_ENTRY_PACKETS_HW,
 815			 nhge->packets_hw))
 816		goto nla_put_failure;
 817
 818	nla_nest_end(skb, nest);
 819	return 0;
 820
 821nla_put_failure:
 822	nla_nest_cancel(skb, nest);
 823	return -EMSGSIZE;
 824}
 825
 826static int nla_put_nh_group_stats(struct sk_buff *skb, struct nexthop *nh,
 827				  u32 op_flags)
 828{
 829	struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
 830	struct nlattr *nest;
 831	bool hw_stats_used;
 832	int err;
 833	int i;
 834
 835	if (nla_put_u32(skb, NHA_HW_STATS_ENABLE, nhg->hw_stats))
 836		goto err_out;
 837
 838	if (op_flags & NHA_OP_FLAG_DUMP_HW_STATS &&
 839	    nhg->hw_stats) {
 840		err = nh_grp_hw_stats_update(nh, &hw_stats_used);
 841		if (err)
 842			goto out;
 843
 844		if (nla_put_u32(skb, NHA_HW_STATS_USED, hw_stats_used))
 845			goto err_out;
 846	}
 847
 848	nest = nla_nest_start(skb, NHA_GROUP_STATS);
 849	if (!nest)
 850		goto err_out;
 851
 852	for (i = 0; i < nhg->num_nh; i++)
 853		if (nla_put_nh_group_stats_entry(skb, &nhg->nh_entries[i],
 854						 op_flags))
 855			goto cancel_out;
 856
 857	nla_nest_end(skb, nest);
 858	return 0;
 859
 860cancel_out:
 861	nla_nest_cancel(skb, nest);
 862err_out:
 863	err = -EMSGSIZE;
 864out:
 865	return err;
 866}
 867
 868static int nla_put_nh_group(struct sk_buff *skb, struct nexthop *nh,
 869			    u32 op_flags, u32 *resp_op_flags)
 870{
 871	struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
 872	struct nexthop_grp *p;
 873	size_t len = nhg->num_nh * sizeof(*p);
 874	struct nlattr *nla;
 875	u16 group_type = 0;
 876	u16 weight;
 877	int i;
 878
 879	*resp_op_flags |= NHA_OP_FLAG_RESP_GRP_RESVD_0;
 880
 881	if (nhg->hash_threshold)
 882		group_type = NEXTHOP_GRP_TYPE_MPATH;
 883	else if (nhg->resilient)
 884		group_type = NEXTHOP_GRP_TYPE_RES;
 885
 886	if (nla_put_u16(skb, NHA_GROUP_TYPE, group_type))
 887		goto nla_put_failure;
 888
 889	nla = nla_reserve(skb, NHA_GROUP, len);
 890	if (!nla)
 891		goto nla_put_failure;
 892
 893	p = nla_data(nla);
 894	for (i = 0; i < nhg->num_nh; ++i) {
 895		weight = nhg->nh_entries[i].weight - 1;
 896
 897		*p++ = (struct nexthop_grp) {
 898			.id = nhg->nh_entries[i].nh->id,
 899			.weight = weight,
 900			.weight_high = weight >> 8,
 901		};
 902	}
 903
 904	if (nhg->resilient && nla_put_nh_group_res(skb, nhg))
 905		goto nla_put_failure;
 906
 907	if (op_flags & NHA_OP_FLAG_DUMP_STATS &&
 908	    nla_put_nh_group_stats(skb, nh, op_flags))
 909		goto nla_put_failure;
 910
 911	return 0;
 912
 913nla_put_failure:
 914	return -EMSGSIZE;
 915}
 916
 917static int nh_fill_node(struct sk_buff *skb, struct nexthop *nh,
 918			int event, u32 portid, u32 seq, unsigned int nlflags,
 919			u32 op_flags)
 920{
 921	struct fib6_nh *fib6_nh;
 922	struct fib_nh *fib_nh;
 923	struct nlmsghdr *nlh;
 924	struct nh_info *nhi;
 925	struct nhmsg *nhm;
 926
 927	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nhm), nlflags);
 928	if (!nlh)
 929		return -EMSGSIZE;
 930
 931	nhm = nlmsg_data(nlh);
 932	nhm->nh_family = AF_UNSPEC;
 933	nhm->nh_flags = nh->nh_flags;
 934	nhm->nh_protocol = nh->protocol;
 935	nhm->nh_scope = 0;
 936	nhm->resvd = 0;
 937
 938	if (nla_put_u32(skb, NHA_ID, nh->id))
 939		goto nla_put_failure;
 940
 941	if (nh->is_group) {
 942		struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
 943		u32 resp_op_flags = 0;
 944
 945		if (nhg->fdb_nh && nla_put_flag(skb, NHA_FDB))
 946			goto nla_put_failure;
 947		if (nla_put_nh_group(skb, nh, op_flags, &resp_op_flags) ||
 948		    nla_put_u32(skb, NHA_OP_FLAGS, resp_op_flags))
 949			goto nla_put_failure;
 950		goto out;
 951	}
 952
 953	nhi = rtnl_dereference(nh->nh_info);
 954	nhm->nh_family = nhi->family;
 955	if (nhi->reject_nh) {
 956		if (nla_put_flag(skb, NHA_BLACKHOLE))
 957			goto nla_put_failure;
 958		goto out;
 959	} else if (nhi->fdb_nh) {
 960		if (nla_put_flag(skb, NHA_FDB))
 961			goto nla_put_failure;
 962	} else {
 963		const struct net_device *dev;
 964
 965		dev = nhi->fib_nhc.nhc_dev;
 966		if (dev && nla_put_u32(skb, NHA_OIF, dev->ifindex))
 967			goto nla_put_failure;
 968	}
 969
 970	nhm->nh_scope = nhi->fib_nhc.nhc_scope;
 971	switch (nhi->family) {
 972	case AF_INET:
 973		fib_nh = &nhi->fib_nh;
 974		if (fib_nh->fib_nh_gw_family &&
 975		    nla_put_be32(skb, NHA_GATEWAY, fib_nh->fib_nh_gw4))
 976			goto nla_put_failure;
 977		break;
 978
 979	case AF_INET6:
 980		fib6_nh = &nhi->fib6_nh;
 981		if (fib6_nh->fib_nh_gw_family &&
 982		    nla_put_in6_addr(skb, NHA_GATEWAY, &fib6_nh->fib_nh_gw6))
 983			goto nla_put_failure;
 984		break;
 985	}
 986
 987	if (lwtunnel_fill_encap(skb, nhi->fib_nhc.nhc_lwtstate,
 988				NHA_ENCAP, NHA_ENCAP_TYPE) < 0)
 989		goto nla_put_failure;
 990
 991out:
 992	nlmsg_end(skb, nlh);
 993	return 0;
 994
 995nla_put_failure:
 996	nlmsg_cancel(skb, nlh);
 997	return -EMSGSIZE;
 998}
 999
1000static size_t nh_nlmsg_size_grp_res(struct nh_group *nhg)
1001{
1002	return nla_total_size(0) +	/* NHA_RES_GROUP */
1003		nla_total_size(2) +	/* NHA_RES_GROUP_BUCKETS */
1004		nla_total_size(4) +	/* NHA_RES_GROUP_IDLE_TIMER */
1005		nla_total_size(4) +	/* NHA_RES_GROUP_UNBALANCED_TIMER */
1006		nla_total_size_64bit(8);/* NHA_RES_GROUP_UNBALANCED_TIME */
1007}
1008
1009static size_t nh_nlmsg_size_grp(struct nexthop *nh, u32 op_flags)
1010{
1011	struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
1012	size_t sz = sizeof(struct nexthop_grp) * nhg->num_nh;
1013	size_t tot = nla_total_size(sz) +
1014		nla_total_size(2) +	/* NHA_GROUP_TYPE */
1015		nla_total_size(0);	/* NHA_FDB */
1016
1017	if (nhg->resilient)
1018		tot += nh_nlmsg_size_grp_res(nhg);
1019
1020	if (op_flags & NHA_OP_FLAG_DUMP_STATS) {
1021		tot += nla_total_size(0) +	  /* NHA_GROUP_STATS */
1022		       nla_total_size(4);	  /* NHA_HW_STATS_ENABLE */
1023		tot += nhg->num_nh *
1024		       (nla_total_size(0) +	  /* NHA_GROUP_STATS_ENTRY */
1025			nla_total_size(4) +	  /* NHA_GROUP_STATS_ENTRY_ID */
1026			nla_total_size_64bit(8)); /* NHA_GROUP_STATS_ENTRY_PACKETS */
1027
1028		if (op_flags & NHA_OP_FLAG_DUMP_HW_STATS) {
1029			tot += nhg->num_nh *
1030			       nla_total_size_64bit(8); /* NHA_GROUP_STATS_ENTRY_PACKETS_HW */
1031			tot += nla_total_size(4);	/* NHA_HW_STATS_USED */
1032		}
1033	}
1034
1035	return tot;
1036}
1037
1038static size_t nh_nlmsg_size_single(struct nexthop *nh)
1039{
1040	struct nh_info *nhi = rtnl_dereference(nh->nh_info);
1041	size_t sz;
1042
1043	/* covers NHA_BLACKHOLE since NHA_OIF and BLACKHOLE
1044	 * are mutually exclusive
1045	 */
1046	sz = nla_total_size(4);  /* NHA_OIF */
1047
1048	switch (nhi->family) {
1049	case AF_INET:
1050		if (nhi->fib_nh.fib_nh_gw_family)
1051			sz += nla_total_size(4);  /* NHA_GATEWAY */
1052		break;
1053
1054	case AF_INET6:
1055		/* NHA_GATEWAY */
1056		if (nhi->fib6_nh.fib_nh_gw_family)
1057			sz += nla_total_size(sizeof(const struct in6_addr));
1058		break;
1059	}
1060
1061	if (nhi->fib_nhc.nhc_lwtstate) {
1062		sz += lwtunnel_get_encap_size(nhi->fib_nhc.nhc_lwtstate);
1063		sz += nla_total_size(2);  /* NHA_ENCAP_TYPE */
1064	}
1065
1066	return sz;
1067}
1068
1069static size_t nh_nlmsg_size(struct nexthop *nh, u32 op_flags)
1070{
1071	size_t sz = NLMSG_ALIGN(sizeof(struct nhmsg));
1072
1073	sz += nla_total_size(4); /* NHA_ID */
1074
1075	if (nh->is_group)
1076		sz += nh_nlmsg_size_grp(nh, op_flags) +
1077		      nla_total_size(4) +	/* NHA_OP_FLAGS */
1078		      0;
1079	else
1080		sz += nh_nlmsg_size_single(nh);
1081
1082	return sz;
1083}
1084
1085static void nexthop_notify(int event, struct nexthop *nh, struct nl_info *info)
1086{
1087	unsigned int nlflags = info->nlh ? info->nlh->nlmsg_flags : 0;
1088	u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0;
1089	struct sk_buff *skb;
1090	int err = -ENOBUFS;
1091
1092	skb = nlmsg_new(nh_nlmsg_size(nh, 0), gfp_any());
1093	if (!skb)
1094		goto errout;
1095
1096	err = nh_fill_node(skb, nh, event, info->portid, seq, nlflags, 0);
1097	if (err < 0) {
1098		/* -EMSGSIZE implies BUG in nh_nlmsg_size() */
1099		WARN_ON(err == -EMSGSIZE);
1100		kfree_skb(skb);
1101		goto errout;
1102	}
1103
1104	rtnl_notify(skb, info->nl_net, info->portid, RTNLGRP_NEXTHOP,
1105		    info->nlh, gfp_any());
1106	return;
1107errout:
1108	rtnl_set_sk_err(info->nl_net, RTNLGRP_NEXTHOP, err);
1109}
1110
1111static unsigned long nh_res_bucket_used_time(const struct nh_res_bucket *bucket)
1112{
1113	return (unsigned long)atomic_long_read(&bucket->used_time);
1114}
1115
1116static unsigned long
1117nh_res_bucket_idle_point(const struct nh_res_table *res_table,
1118			 const struct nh_res_bucket *bucket,
1119			 unsigned long now)
1120{
1121	unsigned long time = nh_res_bucket_used_time(bucket);
1122
1123	/* Bucket was not used since it was migrated. The idle time is now. */
1124	if (time == bucket->migrated_time)
1125		return now;
1126
1127	return time + res_table->idle_timer;
1128}
1129
1130static unsigned long
1131nh_res_table_unb_point(const struct nh_res_table *res_table)
1132{
1133	return res_table->unbalanced_since + res_table->unbalanced_timer;
1134}
1135
1136static void nh_res_bucket_set_idle(const struct nh_res_table *res_table,
1137				   struct nh_res_bucket *bucket)
1138{
1139	unsigned long now = jiffies;
1140
1141	atomic_long_set(&bucket->used_time, (long)now);
1142	bucket->migrated_time = now;
1143}
1144
1145static void nh_res_bucket_set_busy(struct nh_res_bucket *bucket)
1146{
1147	atomic_long_set(&bucket->used_time, (long)jiffies);
1148}
1149
1150static clock_t nh_res_bucket_idle_time(const struct nh_res_bucket *bucket)
1151{
1152	unsigned long used_time = nh_res_bucket_used_time(bucket);
1153
1154	return jiffies_delta_to_clock_t(jiffies - used_time);
1155}
1156
1157static int nh_fill_res_bucket(struct sk_buff *skb, struct nexthop *nh,
1158			      struct nh_res_bucket *bucket, u16 bucket_index,
1159			      int event, u32 portid, u32 seq,
1160			      unsigned int nlflags,
1161			      struct netlink_ext_ack *extack)
1162{
1163	struct nh_grp_entry *nhge = nh_res_dereference(bucket->nh_entry);
1164	struct nlmsghdr *nlh;
1165	struct nlattr *nest;
1166	struct nhmsg *nhm;
1167
1168	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nhm), nlflags);
1169	if (!nlh)
1170		return -EMSGSIZE;
1171
1172	nhm = nlmsg_data(nlh);
1173	nhm->nh_family = AF_UNSPEC;
1174	nhm->nh_flags = bucket->nh_flags;
1175	nhm->nh_protocol = nh->protocol;
1176	nhm->nh_scope = 0;
1177	nhm->resvd = 0;
1178
1179	if (nla_put_u32(skb, NHA_ID, nh->id))
1180		goto nla_put_failure;
1181
1182	nest = nla_nest_start(skb, NHA_RES_BUCKET);
1183	if (!nest)
1184		goto nla_put_failure;
1185
1186	if (nla_put_u16(skb, NHA_RES_BUCKET_INDEX, bucket_index) ||
1187	    nla_put_u32(skb, NHA_RES_BUCKET_NH_ID, nhge->nh->id) ||
1188	    nla_put_u64_64bit(skb, NHA_RES_BUCKET_IDLE_TIME,
1189			      nh_res_bucket_idle_time(bucket),
1190			      NHA_RES_BUCKET_PAD))
1191		goto nla_put_failure_nest;
1192
1193	nla_nest_end(skb, nest);
1194	nlmsg_end(skb, nlh);
1195	return 0;
1196
1197nla_put_failure_nest:
1198	nla_nest_cancel(skb, nest);
1199nla_put_failure:
1200	nlmsg_cancel(skb, nlh);
1201	return -EMSGSIZE;
1202}
1203
1204static void nexthop_bucket_notify(struct nh_res_table *res_table,
1205				  u16 bucket_index)
1206{
1207	struct nh_res_bucket *bucket = &res_table->nh_buckets[bucket_index];
1208	struct nh_grp_entry *nhge = nh_res_dereference(bucket->nh_entry);
1209	struct nexthop *nh = nhge->nh_parent;
1210	struct sk_buff *skb;
1211	int err = -ENOBUFS;
1212
1213	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1214	if (!skb)
1215		goto errout;
1216
1217	err = nh_fill_res_bucket(skb, nh, bucket, bucket_index,
1218				 RTM_NEWNEXTHOPBUCKET, 0, 0, NLM_F_REPLACE,
1219				 NULL);
1220	if (err < 0) {
1221		kfree_skb(skb);
1222		goto errout;
1223	}
1224
1225	rtnl_notify(skb, nh->net, 0, RTNLGRP_NEXTHOP, NULL, GFP_KERNEL);
1226	return;
1227errout:
1228	rtnl_set_sk_err(nh->net, RTNLGRP_NEXTHOP, err);
1229}
1230
1231static bool valid_group_nh(struct nexthop *nh, unsigned int npaths,
1232			   bool *is_fdb, struct netlink_ext_ack *extack)
1233{
1234	if (nh->is_group) {
1235		struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
1236
1237		/* Nesting groups within groups is not supported. */
1238		if (nhg->hash_threshold) {
1239			NL_SET_ERR_MSG(extack,
1240				       "Hash-threshold group can not be a nexthop within a group");
1241			return false;
1242		}
1243		if (nhg->resilient) {
1244			NL_SET_ERR_MSG(extack,
1245				       "Resilient group can not be a nexthop within a group");
1246			return false;
1247		}
1248		*is_fdb = nhg->fdb_nh;
1249	} else {
1250		struct nh_info *nhi = rtnl_dereference(nh->nh_info);
1251
1252		if (nhi->reject_nh && npaths > 1) {
1253			NL_SET_ERR_MSG(extack,
1254				       "Blackhole nexthop can not be used in a group with more than 1 path");
1255			return false;
1256		}
1257		*is_fdb = nhi->fdb_nh;
1258	}
1259
1260	return true;
1261}
1262
1263static int nh_check_attr_fdb_group(struct nexthop *nh, u8 *nh_family,
1264				   struct netlink_ext_ack *extack)
1265{
1266	struct nh_info *nhi;
1267
1268	nhi = rtnl_dereference(nh->nh_info);
1269
1270	if (!nhi->fdb_nh) {
1271		NL_SET_ERR_MSG(extack, "FDB nexthop group can only have fdb nexthops");
1272		return -EINVAL;
1273	}
1274
1275	if (*nh_family == AF_UNSPEC) {
1276		*nh_family = nhi->family;
1277	} else if (*nh_family != nhi->family) {
1278		NL_SET_ERR_MSG(extack, "FDB nexthop group cannot have mixed family nexthops");
1279		return -EINVAL;
1280	}
1281
1282	return 0;
1283}
1284
1285static int nh_check_attr_group(struct net *net,
1286			       struct nlattr *tb[], size_t tb_size,
1287			       u16 nh_grp_type, struct netlink_ext_ack *extack)
1288{
1289	unsigned int len = nla_len(tb[NHA_GROUP]);
1290	struct nexthop_grp *nhg;
1291	unsigned int i, j;
1292
1293	if (!len || len & (sizeof(struct nexthop_grp) - 1)) {
1294		NL_SET_ERR_MSG(extack,
1295			       "Invalid length for nexthop group attribute");
1296		return -EINVAL;
1297	}
1298
1299	/* convert len to number of nexthop ids */
1300	len /= sizeof(*nhg);
1301
1302	nhg = nla_data(tb[NHA_GROUP]);
1303	for (i = 0; i < len; ++i) {
1304		if (nhg[i].resvd2) {
1305			NL_SET_ERR_MSG(extack, "Reserved field in nexthop_grp must be 0");
1306			return -EINVAL;
1307		}
1308		if (nexthop_grp_weight(&nhg[i]) == 0) {
1309			/* 0xffff got passed in, representing weight of 0x10000,
1310			 * which is too heavy.
1311			 */
1312			NL_SET_ERR_MSG(extack, "Invalid value for weight");
1313			return -EINVAL;
1314		}
1315		for (j = i + 1; j < len; ++j) {
1316			if (nhg[i].id == nhg[j].id) {
1317				NL_SET_ERR_MSG(extack, "Nexthop id can not be used twice in a group");
1318				return -EINVAL;
1319			}
1320		}
1321	}
1322
1323	nhg = nla_data(tb[NHA_GROUP]);
1324	for (i = NHA_GROUP_TYPE + 1; i < tb_size; ++i) {
1325		if (!tb[i])
1326			continue;
1327		switch (i) {
1328		case NHA_HW_STATS_ENABLE:
1329		case NHA_FDB:
1330			continue;
1331		case NHA_RES_GROUP:
1332			if (nh_grp_type == NEXTHOP_GRP_TYPE_RES)
1333				continue;
1334			break;
1335		}
1336		NL_SET_ERR_MSG(extack,
1337			       "No other attributes can be set in nexthop groups");
1338		return -EINVAL;
1339	}
1340
1341	return 0;
1342}
1343
1344static int nh_check_attr_group_rtnl(struct net *net, struct nlattr *tb[],
1345				    struct netlink_ext_ack *extack)
1346{
1347	u8 nh_family = AF_UNSPEC;
1348	struct nexthop_grp *nhg;
1349	unsigned int len;
1350	unsigned int i;
1351	u8 nhg_fdb;
1352
1353	len = nla_len(tb[NHA_GROUP]) / sizeof(*nhg);
1354	nhg = nla_data(tb[NHA_GROUP]);
1355	nhg_fdb = !!tb[NHA_FDB];
1356
1357	for (i = 0; i < len; i++) {
1358		struct nexthop *nh;
1359		bool is_fdb_nh;
1360
1361		nh = nexthop_find_by_id(net, nhg[i].id);
1362		if (!nh) {
1363			NL_SET_ERR_MSG(extack, "Invalid nexthop id");
1364			return -EINVAL;
1365		}
1366		if (!valid_group_nh(nh, len, &is_fdb_nh, extack))
1367			return -EINVAL;
1368
1369		if (nhg_fdb && nh_check_attr_fdb_group(nh, &nh_family, extack))
1370			return -EINVAL;
1371
1372		if (!nhg_fdb && is_fdb_nh) {
1373			NL_SET_ERR_MSG(extack, "Non FDB nexthop group cannot have fdb nexthops");
1374			return -EINVAL;
1375		}
1376	}
1377
1378	return 0;
1379}
1380
1381static bool ipv6_good_nh(const struct fib6_nh *nh)
1382{
1383	int state = NUD_REACHABLE;
1384	struct neighbour *n;
1385
1386	rcu_read_lock();
1387
1388	n = __ipv6_neigh_lookup_noref_stub(nh->fib_nh_dev, &nh->fib_nh_gw6);
1389	if (n)
1390		state = READ_ONCE(n->nud_state);
1391
1392	rcu_read_unlock();
1393
1394	return !!(state & NUD_VALID);
1395}
1396
1397static bool ipv4_good_nh(const struct fib_nh *nh)
1398{
1399	int state = NUD_REACHABLE;
1400	struct neighbour *n;
1401
1402	rcu_read_lock();
1403
1404	n = __ipv4_neigh_lookup_noref(nh->fib_nh_dev,
1405				      (__force u32)nh->fib_nh_gw4);
1406	if (n)
1407		state = READ_ONCE(n->nud_state);
1408
1409	rcu_read_unlock();
1410
1411	return !!(state & NUD_VALID);
1412}
1413
1414static bool nexthop_is_good_nh(const struct nexthop *nh)
1415{
1416	struct nh_info *nhi = rcu_dereference(nh->nh_info);
1417
1418	switch (nhi->family) {
1419	case AF_INET:
1420		return ipv4_good_nh(&nhi->fib_nh);
1421	case AF_INET6:
1422		return ipv6_good_nh(&nhi->fib6_nh);
1423	}
1424
1425	return false;
1426}
1427
1428static struct nexthop *nexthop_select_path_fdb(struct nh_group *nhg, int hash)
1429{
1430	int i;
1431
1432	for (i = 0; i < nhg->num_nh; i++) {
1433		struct nh_grp_entry *nhge = &nhg->nh_entries[i];
1434
1435		if (hash > atomic_read(&nhge->hthr.upper_bound))
1436			continue;
1437
1438		nh_grp_entry_stats_inc(nhge);
1439		return nhge->nh;
1440	}
1441
1442	WARN_ON_ONCE(1);
1443	return NULL;
1444}
1445
1446static struct nexthop *nexthop_select_path_hthr(struct nh_group *nhg, int hash)
1447{
1448	struct nh_grp_entry *nhge0 = NULL;
1449	int i;
1450
1451	if (nhg->fdb_nh)
1452		return nexthop_select_path_fdb(nhg, hash);
1453
1454	for (i = 0; i < nhg->num_nh; ++i) {
1455		struct nh_grp_entry *nhge = &nhg->nh_entries[i];
1456
1457		/* nexthops always check if it is good and does
1458		 * not rely on a sysctl for this behavior
1459		 */
1460		if (!nexthop_is_good_nh(nhge->nh))
1461			continue;
1462
1463		if (!nhge0)
1464			nhge0 = nhge;
1465
1466		if (hash > atomic_read(&nhge->hthr.upper_bound))
1467			continue;
1468
1469		nh_grp_entry_stats_inc(nhge);
1470		return nhge->nh;
1471	}
1472
1473	if (!nhge0)
1474		nhge0 = &nhg->nh_entries[0];
1475	nh_grp_entry_stats_inc(nhge0);
1476	return nhge0->nh;
1477}
1478
1479static struct nexthop *nexthop_select_path_res(struct nh_group *nhg, int hash)
1480{
1481	struct nh_res_table *res_table = rcu_dereference(nhg->res_table);
1482	u16 bucket_index = hash % res_table->num_nh_buckets;
1483	struct nh_res_bucket *bucket;
1484	struct nh_grp_entry *nhge;
1485
1486	/* nexthop_select_path() is expected to return a non-NULL value, so
1487	 * skip protocol validation and just hand out whatever there is.
1488	 */
1489	bucket = &res_table->nh_buckets[bucket_index];
1490	nh_res_bucket_set_busy(bucket);
1491	nhge = rcu_dereference(bucket->nh_entry);
1492	nh_grp_entry_stats_inc(nhge);
1493	return nhge->nh;
1494}
1495
1496struct nexthop *nexthop_select_path(struct nexthop *nh, int hash)
1497{
1498	struct nh_group *nhg;
1499
1500	if (!nh->is_group)
1501		return nh;
1502
1503	nhg = rcu_dereference(nh->nh_grp);
1504	if (nhg->hash_threshold)
1505		return nexthop_select_path_hthr(nhg, hash);
1506	else if (nhg->resilient)
1507		return nexthop_select_path_res(nhg, hash);
1508
1509	/* Unreachable. */
1510	return NULL;
1511}
1512EXPORT_SYMBOL_GPL(nexthop_select_path);
1513
1514int nexthop_for_each_fib6_nh(struct nexthop *nh,
1515			     int (*cb)(struct fib6_nh *nh, void *arg),
1516			     void *arg)
1517{
1518	struct nh_info *nhi;
1519	int err;
1520
1521	if (nh->is_group) {
1522		struct nh_group *nhg;
1523		int i;
1524
1525		nhg = rcu_dereference_rtnl(nh->nh_grp);
1526		for (i = 0; i < nhg->num_nh; i++) {
1527			struct nh_grp_entry *nhge = &nhg->nh_entries[i];
1528
1529			nhi = rcu_dereference_rtnl(nhge->nh->nh_info);
1530			err = cb(&nhi->fib6_nh, arg);
1531			if (err)
1532				return err;
1533		}
1534	} else {
1535		nhi = rcu_dereference_rtnl(nh->nh_info);
1536		err = cb(&nhi->fib6_nh, arg);
1537		if (err)
1538			return err;
1539	}
1540
1541	return 0;
1542}
1543EXPORT_SYMBOL_GPL(nexthop_for_each_fib6_nh);
1544
1545static int check_src_addr(const struct in6_addr *saddr,
1546			  struct netlink_ext_ack *extack)
1547{
1548	if (!ipv6_addr_any(saddr)) {
1549		NL_SET_ERR_MSG(extack, "IPv6 routes using source address can not use nexthop objects");
1550		return -EINVAL;
1551	}
1552	return 0;
1553}
1554
1555int fib6_check_nexthop(struct nexthop *nh, struct fib6_config *cfg,
1556		       struct netlink_ext_ack *extack)
1557{
1558	struct nh_info *nhi;
1559	bool is_fdb_nh;
1560
1561	/* fib6_src is unique to a fib6_info and limits the ability to cache
1562	 * routes in fib6_nh within a nexthop that is potentially shared
1563	 * across multiple fib entries. If the config wants to use source
1564	 * routing it can not use nexthop objects. mlxsw also does not allow
1565	 * fib6_src on routes.
1566	 */
1567	if (cfg && check_src_addr(&cfg->fc_src, extack) < 0)
1568		return -EINVAL;
1569
1570	if (nh->is_group) {
1571		struct nh_group *nhg;
1572
1573		nhg = rcu_dereference_rtnl(nh->nh_grp);
1574		if (nhg->has_v4)
1575			goto no_v4_nh;
1576		is_fdb_nh = nhg->fdb_nh;
1577	} else {
1578		nhi = rcu_dereference_rtnl(nh->nh_info);
1579		if (nhi->family == AF_INET)
1580			goto no_v4_nh;
1581		is_fdb_nh = nhi->fdb_nh;
1582	}
1583
1584	if (is_fdb_nh) {
1585		NL_SET_ERR_MSG(extack, "Route cannot point to a fdb nexthop");
1586		return -EINVAL;
1587	}
1588
1589	return 0;
1590no_v4_nh:
1591	NL_SET_ERR_MSG(extack, "IPv6 routes can not use an IPv4 nexthop");
1592	return -EINVAL;
1593}
1594EXPORT_SYMBOL_GPL(fib6_check_nexthop);
1595
1596/* if existing nexthop has ipv6 routes linked to it, need
1597 * to verify this new spec works with ipv6
1598 */
1599static int fib6_check_nh_list(struct nexthop *old, struct nexthop *new,
1600			      struct netlink_ext_ack *extack)
1601{
1602	struct fib6_info *f6i;
1603
1604	if (list_empty(&old->f6i_list))
1605		return 0;
1606
1607	list_for_each_entry(f6i, &old->f6i_list, nh_list) {
1608		if (check_src_addr(&f6i->fib6_src.addr, extack) < 0)
1609			return -EINVAL;
1610	}
1611
1612	return fib6_check_nexthop(new, NULL, extack);
1613}
1614
1615static int nexthop_check_scope(struct nh_info *nhi, u8 scope,
1616			       struct netlink_ext_ack *extack)
1617{
1618	if (scope == RT_SCOPE_HOST && nhi->fib_nhc.nhc_gw_family) {
1619		NL_SET_ERR_MSG(extack,
1620			       "Route with host scope can not have a gateway");
1621		return -EINVAL;
1622	}
1623
1624	if (nhi->fib_nhc.nhc_flags & RTNH_F_ONLINK && scope >= RT_SCOPE_LINK) {
1625		NL_SET_ERR_MSG(extack, "Scope mismatch with nexthop");
1626		return -EINVAL;
1627	}
1628
1629	return 0;
1630}
1631
1632/* Invoked by fib add code to verify nexthop by id is ok with
1633 * config for prefix; parts of fib_check_nh not done when nexthop
1634 * object is used.
1635 */
1636int fib_check_nexthop(struct nexthop *nh, u8 scope,
1637		      struct netlink_ext_ack *extack)
1638{
1639	struct nh_info *nhi;
1640	int err = 0;
1641
1642	if (nh->is_group) {
1643		struct nh_group *nhg;
1644
1645		nhg = rtnl_dereference(nh->nh_grp);
1646		if (nhg->fdb_nh) {
1647			NL_SET_ERR_MSG(extack, "Route cannot point to a fdb nexthop");
1648			err = -EINVAL;
1649			goto out;
1650		}
1651
1652		if (scope == RT_SCOPE_HOST) {
1653			NL_SET_ERR_MSG(extack, "Route with host scope can not have multiple nexthops");
1654			err = -EINVAL;
1655			goto out;
1656		}
1657
1658		/* all nexthops in a group have the same scope */
1659		nhi = rtnl_dereference(nhg->nh_entries[0].nh->nh_info);
1660		err = nexthop_check_scope(nhi, scope, extack);
1661	} else {
1662		nhi = rtnl_dereference(nh->nh_info);
1663		if (nhi->fdb_nh) {
1664			NL_SET_ERR_MSG(extack, "Route cannot point to a fdb nexthop");
1665			err = -EINVAL;
1666			goto out;
1667		}
1668		err = nexthop_check_scope(nhi, scope, extack);
1669	}
1670
1671out:
1672	return err;
1673}
1674
1675static int fib_check_nh_list(struct nexthop *old, struct nexthop *new,
1676			     struct netlink_ext_ack *extack)
1677{
1678	struct fib_info *fi;
1679
1680	list_for_each_entry(fi, &old->fi_list, nh_list) {
1681		int err;
1682
1683		err = fib_check_nexthop(new, fi->fib_scope, extack);
1684		if (err)
1685			return err;
1686	}
1687	return 0;
1688}
1689
1690static bool nh_res_nhge_is_balanced(const struct nh_grp_entry *nhge)
1691{
1692	return nhge->res.count_buckets == nhge->res.wants_buckets;
1693}
1694
1695static bool nh_res_nhge_is_ow(const struct nh_grp_entry *nhge)
1696{
1697	return nhge->res.count_buckets > nhge->res.wants_buckets;
1698}
1699
1700static bool nh_res_nhge_is_uw(const struct nh_grp_entry *nhge)
1701{
1702	return nhge->res.count_buckets < nhge->res.wants_buckets;
1703}
1704
1705static bool nh_res_table_is_balanced(const struct nh_res_table *res_table)
1706{
1707	return list_empty(&res_table->uw_nh_entries);
1708}
1709
1710static void nh_res_bucket_unset_nh(struct nh_res_bucket *bucket)
1711{
1712	struct nh_grp_entry *nhge;
1713
1714	if (bucket->occupied) {
1715		nhge = nh_res_dereference(bucket->nh_entry);
1716		nhge->res.count_buckets--;
1717		bucket->occupied = false;
1718	}
1719}
1720
1721static void nh_res_bucket_set_nh(struct nh_res_bucket *bucket,
1722				 struct nh_grp_entry *nhge)
1723{
1724	nh_res_bucket_unset_nh(bucket);
1725
1726	bucket->occupied = true;
1727	rcu_assign_pointer(bucket->nh_entry, nhge);
1728	nhge->res.count_buckets++;
1729}
1730
1731static bool nh_res_bucket_should_migrate(struct nh_res_table *res_table,
1732					 struct nh_res_bucket *bucket,
1733					 unsigned long *deadline, bool *force)
1734{
1735	unsigned long now = jiffies;
1736	struct nh_grp_entry *nhge;
1737	unsigned long idle_point;
1738
1739	if (!bucket->occupied) {
1740		/* The bucket is not occupied, its NHGE pointer is either
1741		 * NULL or obsolete. We _have to_ migrate: set force.
1742		 */
1743		*force = true;
1744		return true;
1745	}
1746
1747	nhge = nh_res_dereference(bucket->nh_entry);
1748
1749	/* If the bucket is populated by an underweight or balanced
1750	 * nexthop, do not migrate.
1751	 */
1752	if (!nh_res_nhge_is_ow(nhge))
1753		return false;
1754
1755	/* At this point we know that the bucket is populated with an
1756	 * overweight nexthop. It needs to be migrated to a new nexthop if
1757	 * the idle timer of unbalanced timer expired.
1758	 */
1759
1760	idle_point = nh_res_bucket_idle_point(res_table, bucket, now);
1761	if (time_after_eq(now, idle_point)) {
1762		/* The bucket is idle. We _can_ migrate: unset force. */
1763		*force = false;
1764		return true;
1765	}
1766
1767	/* Unbalanced timer of 0 means "never force". */
1768	if (res_table->unbalanced_timer) {
1769		unsigned long unb_point;
1770
1771		unb_point = nh_res_table_unb_point(res_table);
1772		if (time_after(now, unb_point)) {
1773			/* The bucket is not idle, but the unbalanced timer
1774			 * expired. We _can_ migrate, but set force anyway,
1775			 * so that drivers know to ignore activity reports
1776			 * from the HW.
1777			 */
1778			*force = true;
1779			return true;
1780		}
1781
1782		nh_res_time_set_deadline(unb_point, deadline);
1783	}
1784
1785	nh_res_time_set_deadline(idle_point, deadline);
1786	return false;
1787}
1788
1789static bool nh_res_bucket_migrate(struct nh_res_table *res_table,
1790				  u16 bucket_index, bool notify,
1791				  bool notify_nl, bool force)
1792{
1793	struct nh_res_bucket *bucket = &res_table->nh_buckets[bucket_index];
1794	struct nh_grp_entry *new_nhge;
1795	struct netlink_ext_ack extack;
1796	int err;
1797
1798	new_nhge = list_first_entry_or_null(&res_table->uw_nh_entries,
1799					    struct nh_grp_entry,
1800					    res.uw_nh_entry);
1801	if (WARN_ON_ONCE(!new_nhge))
1802		/* If this function is called, "bucket" is either not
1803		 * occupied, or it belongs to a next hop that is
1804		 * overweight. In either case, there ought to be a
1805		 * corresponding underweight next hop.
1806		 */
1807		return false;
1808
1809	if (notify) {
1810		struct nh_grp_entry *old_nhge;
1811
1812		old_nhge = nh_res_dereference(bucket->nh_entry);
1813		err = call_nexthop_res_bucket_notifiers(res_table->net,
1814							res_table->nhg_id,
1815							bucket_index, force,
1816							old_nhge->nh,
1817							new_nhge->nh, &extack);
1818		if (err) {
1819			pr_err_ratelimited("%s\n", extack._msg);
1820			if (!force)
1821				return false;
1822			/* It is not possible to veto a forced replacement, so
1823			 * just clear the hardware flags from the nexthop
1824			 * bucket to indicate to user space that this bucket is
1825			 * not correctly populated in hardware.
1826			 */
1827			bucket->nh_flags &= ~(RTNH_F_OFFLOAD | RTNH_F_TRAP);
1828		}
1829	}
1830
1831	nh_res_bucket_set_nh(bucket, new_nhge);
1832	nh_res_bucket_set_idle(res_table, bucket);
1833
1834	if (notify_nl)
1835		nexthop_bucket_notify(res_table, bucket_index);
1836
1837	if (nh_res_nhge_is_balanced(new_nhge))
1838		list_del(&new_nhge->res.uw_nh_entry);
1839	return true;
1840}
1841
1842#define NH_RES_UPKEEP_DW_MINIMUM_INTERVAL (HZ / 2)
1843
1844static void nh_res_table_upkeep(struct nh_res_table *res_table,
1845				bool notify, bool notify_nl)
1846{
1847	unsigned long now = jiffies;
1848	unsigned long deadline;
1849	u16 i;
1850
1851	/* Deadline is the next time that upkeep should be run. It is the
1852	 * earliest time at which one of the buckets might be migrated.
1853	 * Start at the most pessimistic estimate: either unbalanced_timer
1854	 * from now, or if there is none, idle_timer from now. For each
1855	 * encountered time point, call nh_res_time_set_deadline() to
1856	 * refine the estimate.
1857	 */
1858	if (res_table->unbalanced_timer)
1859		deadline = now + res_table->unbalanced_timer;
1860	else
1861		deadline = now + res_table->idle_timer;
1862
1863	for (i = 0; i < res_table->num_nh_buckets; i++) {
1864		struct nh_res_bucket *bucket = &res_table->nh_buckets[i];
1865		bool force;
1866
1867		if (nh_res_bucket_should_migrate(res_table, bucket,
1868						 &deadline, &force)) {
1869			if (!nh_res_bucket_migrate(res_table, i, notify,
1870						   notify_nl, force)) {
1871				unsigned long idle_point;
1872
1873				/* A driver can override the migration
1874				 * decision if the HW reports that the
1875				 * bucket is actually not idle. Therefore
1876				 * remark the bucket as busy again and
1877				 * update the deadline.
1878				 */
1879				nh_res_bucket_set_busy(bucket);
1880				idle_point = nh_res_bucket_idle_point(res_table,
1881								      bucket,
1882								      now);
1883				nh_res_time_set_deadline(idle_point, &deadline);
1884			}
1885		}
1886	}
1887
1888	/* If the group is still unbalanced, schedule the next upkeep to
1889	 * either the deadline computed above, or the minimum deadline,
1890	 * whichever comes later.
1891	 */
1892	if (!nh_res_table_is_balanced(res_table)) {
1893		unsigned long now = jiffies;
1894		unsigned long min_deadline;
1895
1896		min_deadline = now + NH_RES_UPKEEP_DW_MINIMUM_INTERVAL;
1897		if (time_before(deadline, min_deadline))
1898			deadline = min_deadline;
1899
1900		queue_delayed_work(system_power_efficient_wq,
1901				   &res_table->upkeep_dw, deadline - now);
1902	}
1903}
1904
1905static void nh_res_table_upkeep_dw(struct work_struct *work)
1906{
1907	struct delayed_work *dw = to_delayed_work(work);
1908	struct nh_res_table *res_table;
1909
1910	res_table = container_of(dw, struct nh_res_table, upkeep_dw);
1911	nh_res_table_upkeep(res_table, true, true);
1912}
1913
1914static void nh_res_table_cancel_upkeep(struct nh_res_table *res_table)
1915{
1916	cancel_delayed_work_sync(&res_table->upkeep_dw);
1917}
1918
1919static void nh_res_group_rebalance(struct nh_group *nhg,
1920				   struct nh_res_table *res_table)
1921{
1922	u16 prev_upper_bound = 0;
1923	u32 total = 0;
1924	u32 w = 0;
1925	int i;
1926
1927	INIT_LIST_HEAD(&res_table->uw_nh_entries);
1928
1929	for (i = 0; i < nhg->num_nh; ++i)
1930		total += nhg->nh_entries[i].weight;
1931
1932	for (i = 0; i < nhg->num_nh; ++i) {
1933		struct nh_grp_entry *nhge = &nhg->nh_entries[i];
1934		u16 upper_bound;
1935		u64 btw;
1936
1937		w += nhge->weight;
1938		btw = ((u64)res_table->num_nh_buckets) * w;
1939		upper_bound = DIV_ROUND_CLOSEST_ULL(btw, total);
1940		nhge->res.wants_buckets = upper_bound - prev_upper_bound;
1941		prev_upper_bound = upper_bound;
1942
1943		if (nh_res_nhge_is_uw(nhge)) {
1944			if (list_empty(&res_table->uw_nh_entries))
1945				res_table->unbalanced_since = jiffies;
1946			list_add(&nhge->res.uw_nh_entry,
1947				 &res_table->uw_nh_entries);
1948		}
1949	}
1950}
1951
1952/* Migrate buckets in res_table so that they reference NHGE's from NHG with
1953 * the right NH ID. Set those buckets that do not have a corresponding NHGE
1954 * entry in NHG as not occupied.
1955 */
1956static void nh_res_table_migrate_buckets(struct nh_res_table *res_table,
1957					 struct nh_group *nhg)
1958{
1959	u16 i;
1960
1961	for (i = 0; i < res_table->num_nh_buckets; i++) {
1962		struct nh_res_bucket *bucket = &res_table->nh_buckets[i];
1963		u32 id = rtnl_dereference(bucket->nh_entry)->nh->id;
1964		bool found = false;
1965		int j;
1966
1967		for (j = 0; j < nhg->num_nh; j++) {
1968			struct nh_grp_entry *nhge = &nhg->nh_entries[j];
1969
1970			if (nhge->nh->id == id) {
1971				nh_res_bucket_set_nh(bucket, nhge);
1972				found = true;
1973				break;
1974			}
1975		}
1976
1977		if (!found)
1978			nh_res_bucket_unset_nh(bucket);
1979	}
1980}
1981
1982static void replace_nexthop_grp_res(struct nh_group *oldg,
1983				    struct nh_group *newg)
1984{
1985	/* For NH group replacement, the new NHG might only have a stub
1986	 * hash table with 0 buckets, because the number of buckets was not
1987	 * specified. For NH removal, oldg and newg both reference the same
1988	 * res_table. So in any case, in the following, we want to work
1989	 * with oldg->res_table.
1990	 */
1991	struct nh_res_table *old_res_table = rtnl_dereference(oldg->res_table);
1992	unsigned long prev_unbalanced_since = old_res_table->unbalanced_since;
1993	bool prev_has_uw = !list_empty(&old_res_table->uw_nh_entries);
1994
1995	nh_res_table_cancel_upkeep(old_res_table);
1996	nh_res_table_migrate_buckets(old_res_table, newg);
1997	nh_res_group_rebalance(newg, old_res_table);
1998	if (prev_has_uw && !list_empty(&old_res_table->uw_nh_entries))
1999		old_res_table->unbalanced_since = prev_unbalanced_since;
2000	nh_res_table_upkeep(old_res_table, true, false);
2001}
2002
2003static void nh_hthr_group_rebalance(struct nh_group *nhg)
2004{
2005	u32 total = 0;
2006	u32 w = 0;
2007	int i;
2008
2009	for (i = 0; i < nhg->num_nh; ++i)
2010		total += nhg->nh_entries[i].weight;
2011
2012	for (i = 0; i < nhg->num_nh; ++i) {
2013		struct nh_grp_entry *nhge = &nhg->nh_entries[i];
2014		u32 upper_bound;
2015
2016		w += nhge->weight;
2017		upper_bound = DIV_ROUND_CLOSEST_ULL((u64)w << 31, total) - 1;
2018		atomic_set(&nhge->hthr.upper_bound, upper_bound);
2019	}
2020}
2021
2022static void remove_nh_grp_entry(struct net *net, struct nh_grp_entry *nhge,
2023				struct nl_info *nlinfo,
2024				struct list_head *deferred_free)
2025{
2026	struct nh_grp_entry *nhges, *new_nhges;
2027	struct nexthop *nhp = nhge->nh_parent;
2028	struct netlink_ext_ack extack;
2029	struct nexthop *nh = nhge->nh;
2030	struct nh_group *nhg, *newg;
2031	int i, j, err;
2032
2033	WARN_ON(!nh);
2034
2035	nhg = rtnl_dereference(nhp->nh_grp);
2036	newg = nhg->spare;
2037
2038	/* last entry, keep it visible and remove the parent */
2039	if (nhg->num_nh == 1) {
2040		remove_nexthop(net, nhp, nlinfo);
2041		return;
2042	}
2043
2044	newg->has_v4 = false;
2045	newg->is_multipath = nhg->is_multipath;
2046	newg->hash_threshold = nhg->hash_threshold;
2047	newg->resilient = nhg->resilient;
2048	newg->fdb_nh = nhg->fdb_nh;
2049	newg->num_nh = nhg->num_nh;
2050
2051	/* copy old entries to new except the one getting removed */
2052	nhges = nhg->nh_entries;
2053	new_nhges = newg->nh_entries;
2054	for (i = 0, j = 0; i < nhg->num_nh; ++i) {
2055		struct nh_info *nhi;
2056
2057		/* current nexthop getting removed */
2058		if (nhg->nh_entries[i].nh == nh) {
2059			newg->num_nh--;
2060			continue;
2061		}
2062
2063		nhi = rtnl_dereference(nhges[i].nh->nh_info);
2064		if (nhi->family == AF_INET)
2065			newg->has_v4 = true;
2066
2067		list_del(&nhges[i].nh_list);
2068		new_nhges[j].stats = nhges[i].stats;
2069		new_nhges[j].nh_parent = nhges[i].nh_parent;
2070		new_nhges[j].nh = nhges[i].nh;
2071		new_nhges[j].weight = nhges[i].weight;
2072		list_add(&new_nhges[j].nh_list, &new_nhges[j].nh->grp_list);
2073		j++;
2074	}
2075
2076	if (newg->hash_threshold)
2077		nh_hthr_group_rebalance(newg);
2078	else if (newg->resilient)
2079		replace_nexthop_grp_res(nhg, newg);
2080
2081	rcu_assign_pointer(nhp->nh_grp, newg);
2082
2083	list_del(&nhge->nh_list);
2084	nexthop_put(nhge->nh);
2085	list_add(&nhge->nh_list, deferred_free);
2086
2087	/* Removal of a NH from a resilient group is notified through
2088	 * bucket notifications.
2089	 */
2090	if (newg->hash_threshold) {
2091		err = call_nexthop_notifiers(net, NEXTHOP_EVENT_REPLACE, nhp,
2092					     &extack);
2093		if (err)
2094			pr_err("%s\n", extack._msg);
2095	}
2096
2097	if (nlinfo)
2098		nexthop_notify(RTM_NEWNEXTHOP, nhp, nlinfo);
2099}
2100
2101static void remove_nexthop_from_groups(struct net *net, struct nexthop *nh,
2102				       struct nl_info *nlinfo)
2103{
2104	struct nh_grp_entry *nhge, *tmp;
2105	LIST_HEAD(deferred_free);
2106
2107	/* If there is nothing to do, let's avoid the costly call to
2108	 * synchronize_net()
2109	 */
2110	if (list_empty(&nh->grp_list))
2111		return;
2112
2113	list_for_each_entry_safe(nhge, tmp, &nh->grp_list, nh_list)
2114		remove_nh_grp_entry(net, nhge, nlinfo, &deferred_free);
2115
2116	/* make sure all see the newly published array before releasing rtnl */
2117	synchronize_net();
2118
2119	/* Now safe to free percpu stats — all RCU readers have finished */
2120	list_for_each_entry_safe(nhge, tmp, &deferred_free, nh_list) {
2121		list_del(&nhge->nh_list);
2122		free_percpu(nhge->stats);
2123	}
2124}
2125
2126static void remove_nexthop_group(struct nexthop *nh, struct nl_info *nlinfo)
2127{
2128	struct nh_group *nhg = rcu_dereference_rtnl(nh->nh_grp);
2129	struct nh_res_table *res_table;
2130	int i, num_nh = nhg->num_nh;
2131
2132	for (i = 0; i < num_nh; ++i) {
2133		struct nh_grp_entry *nhge = &nhg->nh_entries[i];
2134
2135		if (WARN_ON(!nhge->nh))
2136			continue;
2137
2138		list_del_init(&nhge->nh_list);
2139	}
2140
2141	if (nhg->resilient) {
2142		res_table = rtnl_dereference(nhg->res_table);
2143		nh_res_table_cancel_upkeep(res_table);
2144	}
2145}
2146
2147/* not called for nexthop replace */
2148static void __remove_nexthop_fib(struct net *net, struct nexthop *nh)
2149{
2150	struct fib6_info *f6i;
2151	bool do_flush = false;
2152	struct fib_info *fi;
2153
2154	list_for_each_entry(fi, &nh->fi_list, nh_list) {
2155		fi->fib_flags |= RTNH_F_DEAD;
2156		do_flush = true;
2157	}
2158	if (do_flush)
2159		fib_flush(net);
2160
2161	spin_lock_bh(&nh->lock);
2162
2163	nh->dead = true;
2164
2165	while (!list_empty(&nh->f6i_list)) {
2166		f6i = list_first_entry(&nh->f6i_list, typeof(*f6i), nh_list);
2167
2168		/* __ip6_del_rt does a release, so do a hold here */
2169		fib6_info_hold(f6i);
2170
2171		spin_unlock_bh(&nh->lock);
2172		ipv6_stub->ip6_del_rt(net, f6i,
2173				      !READ_ONCE(net->ipv4.sysctl_nexthop_compat_mode));
2174
2175		spin_lock_bh(&nh->lock);
2176	}
2177
2178	spin_unlock_bh(&nh->lock);
2179}
2180
2181static void __remove_nexthop(struct net *net, struct nexthop *nh,
2182			     struct nl_info *nlinfo)
2183{
2184	__remove_nexthop_fib(net, nh);
2185
2186	if (nh->is_group) {
2187		remove_nexthop_group(nh, nlinfo);
2188	} else {
2189		struct nh_info *nhi;
2190
2191		nhi = rtnl_dereference(nh->nh_info);
2192		if (nhi->fib_nhc.nhc_dev)
2193			hlist_del(&nhi->dev_hash);
2194
2195		remove_nexthop_from_groups(net, nh, nlinfo);
2196	}
2197}
2198
2199static void remove_nexthop(struct net *net, struct nexthop *nh,
2200			   struct nl_info *nlinfo)
2201{
2202	call_nexthop_notifiers(net, NEXTHOP_EVENT_DEL, nh, NULL);
2203
2204	/* remove from the tree */
2205	rb_erase(&nh->rb_node, &net->nexthop.rb_root);
2206
2207	if (nlinfo)
2208		nexthop_notify(RTM_DELNEXTHOP, nh, nlinfo);
2209
2210	__remove_nexthop(net, nh, nlinfo);
2211	nh_base_seq_inc(net);
2212
2213	nexthop_put(nh);
2214}
2215
2216/* if any FIB entries reference this nexthop, any dst entries
2217 * need to be regenerated
2218 */
2219static void nh_rt_cache_flush(struct net *net, struct nexthop *nh,
2220			      struct nexthop *replaced_nh)
2221{
2222	struct fib6_info *f6i;
2223	struct nh_group *nhg;
2224	int i;
2225
2226	if (!list_empty(&nh->fi_list))
2227		rt_cache_flush(net);
2228
2229	list_for_each_entry(f6i, &nh->f6i_list, nh_list)
2230		ipv6_stub->fib6_update_sernum(net, f6i);
2231
2232	/* if an IPv6 group was replaced, we have to release all old
2233	 * dsts to make sure all refcounts are released
2234	 */
2235	if (!replaced_nh->is_group)
2236		return;
2237
2238	nhg = rtnl_dereference(replaced_nh->nh_grp);
2239	for (i = 0; i < nhg->num_nh; i++) {
2240		struct nh_grp_entry *nhge = &nhg->nh_entries[i];
2241		struct nh_info *nhi = rtnl_dereference(nhge->nh->nh_info);
2242
2243		if (nhi->family == AF_INET6)
2244			ipv6_stub->fib6_nh_release_dsts(&nhi->fib6_nh);
2245	}
2246}
2247
2248static int replace_nexthop_grp(struct net *net, struct nexthop *old,
2249			       struct nexthop *new, const struct nh_config *cfg,
2250			       struct netlink_ext_ack *extack)
2251{
2252	struct nh_res_table *tmp_table = NULL;
2253	struct nh_res_table *new_res_table;
2254	struct nh_res_table *old_res_table;
2255	struct nh_group *oldg, *newg;
2256	int i, err;
2257
2258	if (!new->is_group) {
2259		NL_SET_ERR_MSG(extack, "Can not replace a nexthop group with a nexthop.");
2260		return -EINVAL;
2261	}
2262
2263	oldg = rtnl_dereference(old->nh_grp);
2264	newg = rtnl_dereference(new->nh_grp);
2265
2266	if (newg->hash_threshold != oldg->hash_threshold) {
2267		NL_SET_ERR_MSG(extack, "Can not replace a nexthop group with one of a different type.");
2268		return -EINVAL;
2269	}
2270
2271	if (newg->hash_threshold) {
2272		err = call_nexthop_notifiers(net, NEXTHOP_EVENT_REPLACE, new,
2273					     extack);
2274		if (err)
2275			return err;
2276	} else if (newg->resilient) {
2277		new_res_table = rtnl_dereference(newg->res_table);
2278		old_res_table = rtnl_dereference(oldg->res_table);
2279
2280		/* Accept if num_nh_buckets was not given, but if it was
2281		 * given, demand that the value be correct.
2282		 */
2283		if (cfg->nh_grp_res_has_num_buckets &&
2284		    cfg->nh_grp_res_num_buckets !=
2285		    old_res_table->num_nh_buckets) {
2286			NL_SET_ERR_MSG(extack, "Can not change number of buckets of a resilient nexthop group.");
2287			return -EINVAL;
2288		}
2289
2290		/* Emit a pre-replace notification so that listeners could veto
2291		 * a potentially unsupported configuration. Otherwise,
2292		 * individual bucket replacement notifications would need to be
2293		 * vetoed, which is something that should only happen if the
2294		 * bucket is currently active.
2295		 */
2296		err = call_nexthop_res_table_notifiers(net, new, extack);
2297		if (err)
2298			return err;
2299
2300		if (cfg->nh_grp_res_has_idle_timer)
2301			old_res_table->idle_timer = cfg->nh_grp_res_idle_timer;
2302		if (cfg->nh_grp_res_has_unbalanced_timer)
2303			old_res_table->unbalanced_timer =
2304				cfg->nh_grp_res_unbalanced_timer;
2305
2306		replace_nexthop_grp_res(oldg, newg);
2307
2308		tmp_table = new_res_table;
2309		rcu_assign_pointer(newg->res_table, old_res_table);
2310		rcu_assign_pointer(newg->spare->res_table, old_res_table);
2311	}
2312
2313	/* update parents - used by nexthop code for cleanup */
2314	for (i = 0; i < newg->num_nh; i++)
2315		newg->nh_entries[i].nh_parent = old;
2316
2317	rcu_assign_pointer(old->nh_grp, newg);
2318
2319	/* Make sure concurrent readers are not using 'oldg' anymore. */
2320	synchronize_net();
2321
2322	if (newg->resilient) {
2323		rcu_assign_pointer(oldg->res_table, tmp_table);
2324		rcu_assign_pointer(oldg->spare->res_table, tmp_table);
2325	}
2326
2327	for (i = 0; i < oldg->num_nh; i++)
2328		oldg->nh_entries[i].nh_parent = new;
2329
2330	rcu_assign_pointer(new->nh_grp, oldg);
2331
2332	return 0;
2333}
2334
2335static void nh_group_v4_update(struct nh_group *nhg)
2336{
2337	struct nh_grp_entry *nhges;
2338	bool has_v4 = false;
2339	int i;
2340
2341	nhges = nhg->nh_entries;
2342	for (i = 0; i < nhg->num_nh; i++) {
2343		struct nh_info *nhi;
2344
2345		nhi = rtnl_dereference(nhges[i].nh->nh_info);
2346		if (nhi->family == AF_INET)
2347			has_v4 = true;
2348	}
2349	nhg->has_v4 = has_v4;
2350}
2351
2352static int replace_nexthop_single_notify_res(struct net *net,
2353					     struct nh_res_table *res_table,
2354					     struct nexthop *old,
2355					     struct nh_info *oldi,
2356					     struct nh_info *newi,
2357					     struct netlink_ext_ack *extack)
2358{
2359	u32 nhg_id = res_table->nhg_id;
2360	int err;
2361	u16 i;
2362
2363	for (i = 0; i < res_table->num_nh_buckets; i++) {
2364		struct nh_res_bucket *bucket = &res_table->nh_buckets[i];
2365		struct nh_grp_entry *nhge;
2366
2367		nhge = rtnl_dereference(bucket->nh_entry);
2368		if (nhge->nh == old) {
2369			err = __call_nexthop_res_bucket_notifiers(net, nhg_id,
2370								  i, true,
2371								  oldi, newi,
2372								  extack);
2373			if (err)
2374				goto err_notify;
2375		}
2376	}
2377
2378	return 0;
2379
2380err_notify:
2381	while (i-- > 0) {
2382		struct nh_res_bucket *bucket = &res_table->nh_buckets[i];
2383		struct nh_grp_entry *nhge;
2384
2385		nhge = rtnl_dereference(bucket->nh_entry);
2386		if (nhge->nh == old)
2387			__call_nexthop_res_bucket_notifiers(net, nhg_id, i,
2388							    true, newi, oldi,
2389							    extack);
2390	}
2391	return err;
2392}
2393
2394static int replace_nexthop_single_notify(struct net *net,
2395					 struct nexthop *group_nh,
2396					 struct nexthop *old,
2397					 struct nh_info *oldi,
2398					 struct nh_info *newi,
2399					 struct netlink_ext_ack *extack)
2400{
2401	struct nh_group *nhg = rtnl_dereference(group_nh->nh_grp);
2402	struct nh_res_table *res_table;
2403
2404	if (nhg->hash_threshold) {
2405		return call_nexthop_notifiers(net, NEXTHOP_EVENT_REPLACE,
2406					      group_nh, extack);
2407	} else if (nhg->resilient) {
2408		res_table = rtnl_dereference(nhg->res_table);
2409		return replace_nexthop_single_notify_res(net, res_table,
2410							 old, oldi, newi,
2411							 extack);
2412	}
2413
2414	return -EINVAL;
2415}
2416
2417static int replace_nexthop_single(struct net *net, struct nexthop *old,
2418				  struct nexthop *new,
2419				  struct netlink_ext_ack *extack)
2420{
2421	u8 old_protocol, old_nh_flags;
2422	struct nh_info *oldi, *newi;
2423	struct nh_grp_entry *nhge;
2424	int err;
2425
2426	if (new->is_group) {
2427		NL_SET_ERR_MSG(extack, "Can not replace a nexthop with a nexthop group.");
2428		return -EINVAL;
2429	}
2430
2431	if (!list_empty(&old->grp_list) &&
2432	    rtnl_dereference(new->nh_info)->fdb_nh !=
2433	    rtnl_dereference(old->nh_info)->fdb_nh) {
2434		NL_SET_ERR_MSG(extack, "Cannot change nexthop FDB status while in a group");
2435		return -EINVAL;
2436	}
2437
2438	err = call_nexthop_notifiers(net, NEXTHOP_EVENT_REPLACE, new, extack);
2439	if (err)
2440		return err;
2441
2442	/* Hardware flags were set on 'old' as 'new' is not in the red-black
2443	 * tree. Therefore, inherit the flags from 'old' to 'new'.
2444	 */
2445	new->nh_flags |= old->nh_flags & (RTNH_F_OFFLOAD | RTNH_F_TRAP);
2446
2447	oldi = rtnl_dereference(old->nh_info);
2448	newi = rtnl_dereference(new->nh_info);
2449
2450	newi->nh_parent = old;
2451	oldi->nh_parent = new;
2452
2453	old_protocol = old->protocol;
2454	old_nh_flags = old->nh_flags;
2455
2456	old->protocol = new->protocol;
2457	old->nh_flags = new->nh_flags;
2458
2459	rcu_assign_pointer(old->nh_info, newi);
2460	rcu_assign_pointer(new->nh_info, oldi);
2461
2462	/* Send a replace notification for all the groups using the nexthop. */
2463	list_for_each_entry(nhge, &old->grp_list, nh_list) {
2464		struct nexthop *nhp = nhge->nh_parent;
2465
2466		err = replace_nexthop_single_notify(net, nhp, old, oldi, newi,
2467						    extack);
2468		if (err)
2469			goto err_notify;
2470	}
2471
2472	/* When replacing an IPv4 nexthop with an IPv6 nexthop, potentially
2473	 * update IPv4 indication in all the groups using the nexthop.
2474	 */
2475	if (oldi->family == AF_INET && newi->family == AF_INET6) {
2476		list_for_each_entry(nhge, &old->grp_list, nh_list) {
2477			struct nexthop *nhp = nhge->nh_parent;
2478			struct nh_group *nhg;
2479
2480			nhg = rtnl_dereference(nhp->nh_grp);
2481			nh_group_v4_update(nhg);
2482		}
2483	}
2484
2485	return 0;
2486
2487err_notify:
2488	rcu_assign_pointer(new->nh_info, newi);
2489	rcu_assign_pointer(old->nh_info, oldi);
2490	old->nh_flags = old_nh_flags;
2491	old->protocol = old_protocol;
2492	oldi->nh_parent = old;
2493	newi->nh_parent = new;
2494	list_for_each_entry_continue_reverse(nhge, &old->grp_list, nh_list) {
2495		struct nexthop *nhp = nhge->nh_parent;
2496
2497		replace_nexthop_single_notify(net, nhp, old, newi, oldi, NULL);
2498	}
2499	call_nexthop_notifiers(net, NEXTHOP_EVENT_REPLACE, old, extack);
2500	return err;
2501}
2502
2503static void __nexthop_replace_notify(struct net *net, struct nexthop *nh,
2504				     struct nl_info *info)
2505{
2506	struct fib6_info *f6i;
2507
2508	if (!list_empty(&nh->fi_list)) {
2509		struct fib_info *fi;
2510
2511		/* expectation is a few fib_info per nexthop and then
2512		 * a lot of routes per fib_info. So mark the fib_info
2513		 * and then walk the fib tables once
2514		 */
2515		list_for_each_entry(fi, &nh->fi_list, nh_list)
2516			fi->nh_updated = true;
2517
2518		fib_info_notify_update(net, info);
2519
2520		list_for_each_entry(fi, &nh->fi_list, nh_list)
2521			fi->nh_updated = false;
2522	}
2523
2524	list_for_each_entry(f6i, &nh->f6i_list, nh_list)
2525		ipv6_stub->fib6_rt_update(net, f6i, info);
2526}
2527
2528/* send RTM_NEWROUTE with REPLACE flag set for all FIB entries
2529 * linked to this nexthop and for all groups that the nexthop
2530 * is a member of
2531 */
2532static void nexthop_replace_notify(struct net *net, struct nexthop *nh,
2533				   struct nl_info *info)
2534{
2535	struct nh_grp_entry *nhge;
2536
2537	__nexthop_replace_notify(net, nh, info);
2538
2539	list_for_each_entry(nhge, &nh->grp_list, nh_list)
2540		__nexthop_replace_notify(net, nhge->nh_parent, info);
2541}
2542
2543static int replace_nexthop(struct net *net, struct nexthop *old,
2544			   struct nexthop *new, const struct nh_config *cfg,
2545			   struct netlink_ext_ack *extack)
2546{
2547	bool new_is_reject = false;
2548	struct nh_grp_entry *nhge;
2549	int err;
2550
2551	/* check that existing FIB entries are ok with the
2552	 * new nexthop definition
2553	 */
2554	err = fib_check_nh_list(old, new, extack);
2555	if (err)
2556		return err;
2557
2558	err = fib6_check_nh_list(old, new, extack);
2559	if (err)
2560		return err;
2561
2562	if (!new->is_group) {
2563		struct nh_info *nhi = rtnl_dereference(new->nh_info);
2564
2565		new_is_reject = nhi->reject_nh;
2566	}
2567
2568	list_for_each_entry(nhge, &old->grp_list, nh_list) {
2569		/* if new nexthop is a blackhole, any groups using this
2570		 * nexthop cannot have more than 1 path
2571		 */
2572		if (new_is_reject &&
2573		    nexthop_num_path(nhge->nh_parent) > 1) {
2574			NL_SET_ERR_MSG(extack, "Blackhole nexthop can not be a member of a group with more than one path");
2575			return -EINVAL;
2576		}
2577
2578		err = fib_check_nh_list(nhge->nh_parent, new, extack);
2579		if (err)
2580			return err;
2581
2582		err = fib6_check_nh_list(nhge->nh_parent, new, extack);
2583		if (err)
2584			return err;
2585	}
2586
2587	if (old->is_group)
2588		err = replace_nexthop_grp(net, old, new, cfg, extack);
2589	else
2590		err = replace_nexthop_single(net, old, new, extack);
2591
2592	if (!err) {
2593		nh_rt_cache_flush(net, old, new);
2594
2595		__remove_nexthop(net, new, NULL);
2596		nexthop_put(new);
2597	}
2598
2599	return err;
2600}
2601
2602/* called with rtnl_lock held */
2603static int insert_nexthop(struct net *net, struct nexthop *new_nh,
2604			  struct nh_config *cfg, struct netlink_ext_ack *extack)
2605{
2606	struct rb_node **pp, *parent = NULL, *next;
2607	struct rb_root *root = &net->nexthop.rb_root;
2608	bool replace = !!(cfg->nlflags & NLM_F_REPLACE);
2609	bool create = !!(cfg->nlflags & NLM_F_CREATE);
2610	u32 new_id = new_nh->id;
2611	int replace_notify = 0;
2612	int rc = -EEXIST;
2613
2614	pp = &root->rb_node;
2615	while (1) {
2616		struct nexthop *nh;
2617
2618		next = *pp;
2619		if (!next)
2620			break;
2621
2622		parent = next;
2623
2624		nh = rb_entry(parent, struct nexthop, rb_node);
2625		if (new_id < nh->id) {
2626			pp = &next->rb_left;
2627		} else if (new_id > nh->id) {
2628			pp = &next->rb_right;
2629		} else if (replace) {
2630			rc = replace_nexthop(net, nh, new_nh, cfg, extack);
2631			if (!rc) {
2632				new_nh = nh; /* send notification with old nh */
2633				replace_notify = 1;
2634			}
2635			goto out;
2636		} else {
2637			/* id already exists and not a replace */
2638			goto out;
2639		}
2640	}
2641
2642	if (replace && !create) {
2643		NL_SET_ERR_MSG(extack, "Replace specified without create and no entry exists");
2644		rc = -ENOENT;
2645		goto out;
2646	}
2647
2648	if (new_nh->is_group) {
2649		struct nh_group *nhg = rtnl_dereference(new_nh->nh_grp);
2650		struct nh_res_table *res_table;
2651
2652		if (nhg->resilient) {
2653			res_table = rtnl_dereference(nhg->res_table);
2654
2655			/* Not passing the number of buckets is OK when
2656			 * replacing, but not when creating a new group.
2657			 */
2658			if (!cfg->nh_grp_res_has_num_buckets) {
2659				NL_SET_ERR_MSG(extack, "Number of buckets not specified for nexthop group insertion");
2660				rc = -EINVAL;
2661				goto out;
2662			}
2663
2664			nh_res_group_rebalance(nhg, res_table);
2665
2666			/* Do not send bucket notifications, we do full
2667			 * notification below.
2668			 */
2669			nh_res_table_upkeep(res_table, false, false);
2670		}
2671	}
2672
2673	rb_link_node_rcu(&new_nh->rb_node, parent, pp);
2674	rb_insert_color(&new_nh->rb_node, root);
2675
2676	/* The initial insertion is a full notification for hash-threshold as
2677	 * well as resilient groups.
2678	 */
2679	rc = call_nexthop_notifiers(net, NEXTHOP_EVENT_REPLACE, new_nh, extack);
2680	if (rc)
2681		rb_erase(&new_nh->rb_node, &net->nexthop.rb_root);
2682
2683out:
2684	if (!rc) {
2685		nh_base_seq_inc(net);
2686		nexthop_notify(RTM_NEWNEXTHOP, new_nh, &cfg->nlinfo);
2687		if (replace_notify &&
2688		    READ_ONCE(net->ipv4.sysctl_nexthop_compat_mode))
2689			nexthop_replace_notify(net, new_nh, &cfg->nlinfo);
2690	}
2691
2692	return rc;
2693}
2694
2695/* rtnl */
2696/* remove all nexthops tied to a device being deleted */
2697static void nexthop_flush_dev(struct net_device *dev, unsigned long event)
2698{
2699	unsigned int hash = nh_dev_hashfn(dev->ifindex);
2700	struct net *net = dev_net(dev);
2701	struct hlist_head *head = &net->nexthop.devhash[hash];
2702	struct hlist_node *n;
2703	struct nh_info *nhi;
2704
2705	hlist_for_each_entry_safe(nhi, n, head, dev_hash) {
2706		if (nhi->fib_nhc.nhc_dev != dev)
2707			continue;
2708
2709		if (nhi->reject_nh &&
2710		    (event == NETDEV_DOWN || event == NETDEV_CHANGE))
2711			continue;
2712
2713		remove_nexthop(net, nhi->nh_parent, NULL);
2714	}
2715}
2716
2717/* rtnl; called when net namespace is deleted */
2718static void flush_all_nexthops(struct net *net)
2719{
2720	struct rb_root *root = &net->nexthop.rb_root;
2721	struct rb_node *node;
2722	struct nexthop *nh;
2723
2724	while ((node = rb_first(root))) {
2725		nh = rb_entry(node, struct nexthop, rb_node);
2726		remove_nexthop(net, nh, NULL);
2727		cond_resched();
2728	}
2729}
2730
2731static struct nexthop *nexthop_create_group(struct net *net,
2732					    struct nh_config *cfg)
2733{
2734	struct nlattr *grps_attr = cfg->nh_grp;
2735	struct nexthop_grp *entry = nla_data(grps_attr);
2736	u16 num_nh = nla_len(grps_attr) / sizeof(*entry);
2737	struct nh_group *nhg;
2738	struct nexthop *nh;
2739	int err;
2740	int i;
2741
2742	nh = nexthop_alloc();
2743	if (!nh)
2744		return ERR_PTR(-ENOMEM);
2745
2746	nh->is_group = 1;
2747
2748	nhg = nexthop_grp_alloc(num_nh);
2749	if (!nhg) {
2750		kfree(nh);
2751		return ERR_PTR(-ENOMEM);
2752	}
2753
2754	/* spare group used for removals */
2755	nhg->spare = nexthop_grp_alloc(num_nh);
2756	if (!nhg->spare) {
2757		kfree(nhg);
2758		kfree(nh);
2759		return ERR_PTR(-ENOMEM);
2760	}
2761	nhg->spare->spare = nhg;
2762
2763	for (i = 0; i < nhg->num_nh; ++i) {
2764		struct nexthop *nhe;
2765		struct nh_info *nhi;
2766
2767		nhe = nexthop_find_by_id(net, entry[i].id);
2768		if (!nexthop_get(nhe)) {
2769			err = -ENOENT;
2770			goto out_no_nh;
2771		}
2772
2773		nhi = rtnl_dereference(nhe->nh_info);
2774		if (nhi->family == AF_INET)
2775			nhg->has_v4 = true;
2776
2777		nhg->nh_entries[i].stats =
2778			netdev_alloc_pcpu_stats(struct nh_grp_entry_stats);
2779		if (!nhg->nh_entries[i].stats) {
2780			err = -ENOMEM;
2781			nexthop_put(nhe);
2782			goto out_no_nh;
2783		}
2784		nhg->nh_entries[i].nh = nhe;
2785		nhg->nh_entries[i].weight = nexthop_grp_weight(&entry[i]);
2786
2787		list_add(&nhg->nh_entries[i].nh_list, &nhe->grp_list);
2788		nhg->nh_entries[i].nh_parent = nh;
2789	}
2790
2791	if (cfg->nh_grp_type == NEXTHOP_GRP_TYPE_MPATH) {
2792		nhg->hash_threshold = 1;
2793		nhg->is_multipath = true;
2794	} else if (cfg->nh_grp_type == NEXTHOP_GRP_TYPE_RES) {
2795		struct nh_res_table *res_table;
2796
2797		res_table = nexthop_res_table_alloc(net, cfg->nh_id, cfg);
2798		if (!res_table) {
2799			err = -ENOMEM;
2800			goto out_no_nh;
2801		}
2802
2803		rcu_assign_pointer(nhg->spare->res_table, res_table);
2804		rcu_assign_pointer(nhg->res_table, res_table);
2805		nhg->resilient = true;
2806		nhg->is_multipath = true;
2807	}
2808
2809	WARN_ON_ONCE(nhg->hash_threshold + nhg->resilient != 1);
2810
2811	if (nhg->hash_threshold)
2812		nh_hthr_group_rebalance(nhg);
2813
2814	if (cfg->nh_fdb)
2815		nhg->fdb_nh = 1;
2816
2817	if (cfg->nh_hw_stats)
2818		nhg->hw_stats = true;
2819
2820	rcu_assign_pointer(nh->nh_grp, nhg);
2821
2822	return nh;
2823
2824out_no_nh:
2825	for (i--; i >= 0; --i) {
2826		list_del(&nhg->nh_entries[i].nh_list);
2827		free_percpu(nhg->nh_entries[i].stats);
2828		nexthop_put(nhg->nh_entries[i].nh);
2829	}
2830
2831	kfree(nhg->spare);
2832	kfree(nhg);
2833	kfree(nh);
2834
2835	return ERR_PTR(err);
2836}
2837
2838static int nh_create_ipv4(struct net *net, struct nexthop *nh,
2839			  struct nh_info *nhi, struct nh_config *cfg,
2840			  struct netlink_ext_ack *extack)
2841{
2842	struct fib_nh *fib_nh = &nhi->fib_nh;
2843	struct fib_config fib_cfg = {
2844		.fc_oif   = cfg->nh_ifindex,
2845		.fc_gw4   = cfg->gw.ipv4,
2846		.fc_gw_family = cfg->gw.ipv4 ? AF_INET : 0,
2847		.fc_flags = cfg->nh_flags,
2848		.fc_nlinfo = cfg->nlinfo,
2849		.fc_encap = cfg->nh_encap,
2850		.fc_encap_type = cfg->nh_encap_type,
2851	};
2852	u32 tb_id = (cfg->dev ? l3mdev_fib_table(cfg->dev) : RT_TABLE_MAIN);
2853	int err;
2854
2855	err = fib_nh_init(net, fib_nh, &fib_cfg, 1, extack);
2856	if (err) {
2857		fib_nh_release(net, fib_nh);
2858		goto out;
2859	}
2860
2861	if (nhi->fdb_nh)
2862		goto out;
2863
2864	/* sets nh_dev if successful */
2865	err = fib_check_nh(net, fib_nh, tb_id, 0, extack);
2866	if (!err) {
2867		nh->nh_flags = fib_nh->fib_nh_flags;
2868		fib_info_update_nhc_saddr(net, &fib_nh->nh_common,
2869					  !fib_nh->fib_nh_scope ? 0 : fib_nh->fib_nh_scope - 1);
2870	} else {
2871		fib_nh_release(net, fib_nh);
2872	}
2873out:
2874	return err;
2875}
2876
2877static int nh_create_ipv6(struct net *net,  struct nexthop *nh,
2878			  struct nh_info *nhi, struct nh_config *cfg,
2879			  struct netlink_ext_ack *extack)
2880{
2881	struct fib6_nh *fib6_nh = &nhi->fib6_nh;
2882	struct fib6_config fib6_cfg = {
2883		.fc_table = l3mdev_fib_table(cfg->dev),
2884		.fc_ifindex = cfg->nh_ifindex,
2885		.fc_gateway = cfg->gw.ipv6,
2886		.fc_flags = cfg->nh_flags,
2887		.fc_nlinfo = cfg->nlinfo,
2888		.fc_encap = cfg->nh_encap,
2889		.fc_encap_type = cfg->nh_encap_type,
2890		.fc_is_fdb = cfg->nh_fdb,
2891	};
2892	int err;
2893
2894	if (!ipv6_addr_any(&cfg->gw.ipv6))
2895		fib6_cfg.fc_flags |= RTF_GATEWAY;
2896
2897	/* sets nh_dev if successful */
2898	err = ipv6_stub->fib6_nh_init(net, fib6_nh, &fib6_cfg, GFP_KERNEL,
2899				      extack);
2900	if (err) {
2901		/* IPv6 is not enabled, don't call fib6_nh_release */
2902		if (err == -EAFNOSUPPORT)
2903			goto out;
2904		ipv6_stub->fib6_nh_release(fib6_nh);
2905	} else {
2906		nh->nh_flags = fib6_nh->fib_nh_flags;
2907	}
2908out:
2909	return err;
2910}
2911
2912static struct nexthop *nexthop_create(struct net *net, struct nh_config *cfg,
2913				      struct netlink_ext_ack *extack)
2914{
2915	struct nh_info *nhi;
2916	struct nexthop *nh;
2917	int err = 0;
2918
2919	nh = nexthop_alloc();
2920	if (!nh)
2921		return ERR_PTR(-ENOMEM);
2922
2923	nhi = kzalloc(sizeof(*nhi), GFP_KERNEL);
2924	if (!nhi) {
2925		kfree(nh);
2926		return ERR_PTR(-ENOMEM);
2927	}
2928
2929	nh->nh_flags = cfg->nh_flags;
2930	nh->net = net;
2931
2932	nhi->nh_parent = nh;
2933	nhi->family = cfg->nh_family;
2934	nhi->fib_nhc.nhc_scope = RT_SCOPE_LINK;
2935
2936	if (cfg->nh_fdb)
2937		nhi->fdb_nh = 1;
2938
2939	if (cfg->nh_blackhole) {
2940		nhi->reject_nh = 1;
2941		cfg->nh_ifindex = net->loopback_dev->ifindex;
2942	}
2943
2944	switch (cfg->nh_family) {
2945	case AF_INET:
2946		err = nh_create_ipv4(net, nh, nhi, cfg, extack);
2947		break;
2948	case AF_INET6:
2949		err = nh_create_ipv6(net, nh, nhi, cfg, extack);
2950		break;
2951	}
2952
2953	if (err) {
2954		kfree(nhi);
2955		kfree(nh);
2956		return ERR_PTR(err);
2957	}
2958
2959	/* add the entry to the device based hash */
2960	if (!nhi->fdb_nh)
2961		nexthop_devhash_add(net, nhi);
2962
2963	rcu_assign_pointer(nh->nh_info, nhi);
2964
2965	return nh;
2966}
2967
2968/* called with rtnl lock held */
2969static struct nexthop *nexthop_add(struct net *net, struct nh_config *cfg,
2970				   struct netlink_ext_ack *extack)
2971{
2972	struct nexthop *nh;
2973	int err;
2974
2975	if (!cfg->nh_id) {
2976		cfg->nh_id = nh_find_unused_id(net);
2977		if (!cfg->nh_id) {
2978			NL_SET_ERR_MSG(extack, "No unused id");
2979			return ERR_PTR(-EINVAL);
2980		}
2981	}
2982
2983	if (cfg->nh_grp)
2984		nh = nexthop_create_group(net, cfg);
2985	else
2986		nh = nexthop_create(net, cfg, extack);
2987
2988	if (IS_ERR(nh))
2989		return nh;
2990
2991	refcount_set(&nh->refcnt, 1);
2992	nh->id = cfg->nh_id;
2993	nh->protocol = cfg->nh_protocol;
2994	nh->net = net;
2995
2996	err = insert_nexthop(net, nh, cfg, extack);
2997	if (err) {
2998		__remove_nexthop(net, nh, NULL);
2999		nexthop_put(nh);
3000		nh = ERR_PTR(err);
3001	}
3002
3003	return nh;
3004}
3005
3006static int rtm_nh_get_timer(struct nlattr *attr, unsigned long fallback,
3007			    unsigned long *timer_p, bool *has_p,
3008			    struct netlink_ext_ack *extack)
3009{
3010	unsigned long timer;
3011	u32 value;
3012
3013	if (!attr) {
3014		*timer_p = fallback;
3015		*has_p = false;
3016		return 0;
3017	}
3018
3019	value = nla_get_u32(attr);
3020	timer = clock_t_to_jiffies(value);
3021	if (timer == ~0UL) {
3022		NL_SET_ERR_MSG(extack, "Timer value too large");
3023		return -EINVAL;
3024	}
3025
3026	*timer_p = timer;
3027	*has_p = true;
3028	return 0;
3029}
3030
3031static int rtm_to_nh_config_grp_res(struct nlattr *res, struct nh_config *cfg,
3032				    struct netlink_ext_ack *extack)
3033{
3034	struct nlattr *tb[ARRAY_SIZE(rtm_nh_res_policy_new)] = {};
3035	int err;
3036
3037	if (res) {
3038		err = nla_parse_nested(tb,
3039				       ARRAY_SIZE(rtm_nh_res_policy_new) - 1,
3040				       res, rtm_nh_res_policy_new, extack);
3041		if (err < 0)
3042			return err;
3043	}
3044
3045	if (tb[NHA_RES_GROUP_BUCKETS]) {
3046		cfg->nh_grp_res_num_buckets =
3047			nla_get_u16(tb[NHA_RES_GROUP_BUCKETS]);
3048		cfg->nh_grp_res_has_num_buckets = true;
3049		if (!cfg->nh_grp_res_num_buckets) {
3050			NL_SET_ERR_MSG(extack, "Number of buckets needs to be non-0");
3051			return -EINVAL;
3052		}
3053	}
3054
3055	err = rtm_nh_get_timer(tb[NHA_RES_GROUP_IDLE_TIMER],
3056			       NH_RES_DEFAULT_IDLE_TIMER,
3057			       &cfg->nh_grp_res_idle_timer,
3058			       &cfg->nh_grp_res_has_idle_timer,
3059			       extack);
3060	if (err)
3061		return err;
3062
3063	return rtm_nh_get_timer(tb[NHA_RES_GROUP_UNBALANCED_TIMER],
3064				NH_RES_DEFAULT_UNBALANCED_TIMER,
3065				&cfg->nh_grp_res_unbalanced_timer,
3066				&cfg->nh_grp_res_has_unbalanced_timer,
3067				extack);
3068}
3069
3070static int rtm_to_nh_config(struct net *net, struct sk_buff *skb,
3071			    struct nlmsghdr *nlh, struct nlattr **tb,
3072			    struct nh_config *cfg,
3073			    struct netlink_ext_ack *extack)
3074{
3075	struct nhmsg *nhm = nlmsg_data(nlh);
3076	int err;
3077
3078	err = -EINVAL;
3079	if (nhm->resvd || nhm->nh_scope) {
3080		NL_SET_ERR_MSG(extack, "Invalid values in ancillary header");
3081		goto out;
3082	}
3083	if (nhm->nh_flags & ~NEXTHOP_VALID_USER_FLAGS) {
3084		NL_SET_ERR_MSG(extack, "Invalid nexthop flags in ancillary header");
3085		goto out;
3086	}
3087
3088	switch (nhm->nh_family) {
3089	case AF_INET:
3090	case AF_INET6:
3091		break;
3092	case AF_UNSPEC:
3093		if (tb[NHA_GROUP])
3094			break;
3095		fallthrough;
3096	default:
3097		NL_SET_ERR_MSG(extack, "Invalid address family");
3098		goto out;
3099	}
3100
3101	memset(cfg, 0, sizeof(*cfg));
3102	cfg->nlflags = nlh->nlmsg_flags;
3103	cfg->nlinfo.portid = NETLINK_CB(skb).portid;
3104	cfg->nlinfo.nlh = nlh;
3105	cfg->nlinfo.nl_net = net;
3106
3107	cfg->nh_family = nhm->nh_family;
3108	cfg->nh_protocol = nhm->nh_protocol;
3109	cfg->nh_flags = nhm->nh_flags;
3110
3111	if (tb[NHA_ID])
3112		cfg->nh_id = nla_get_u32(tb[NHA_ID]);
3113
3114	if (tb[NHA_FDB]) {
3115		if (tb[NHA_OIF] || tb[NHA_BLACKHOLE] ||
3116		    tb[NHA_ENCAP]   || tb[NHA_ENCAP_TYPE]) {
3117			NL_SET_ERR_MSG(extack, "Fdb attribute can not be used with encap, oif or blackhole");
3118			goto out;
3119		}
3120		if (nhm->nh_flags) {
3121			NL_SET_ERR_MSG(extack, "Unsupported nexthop flags in ancillary header");
3122			goto out;
3123		}
3124		cfg->nh_fdb = nla_get_flag(tb[NHA_FDB]);
3125	}
3126
3127	if (tb[NHA_GROUP]) {
3128		if (nhm->nh_family != AF_UNSPEC) {
3129			NL_SET_ERR_MSG(extack, "Invalid family for group");
3130			goto out;
3131		}
3132		cfg->nh_grp = tb[NHA_GROUP];
3133
3134		cfg->nh_grp_type = NEXTHOP_GRP_TYPE_MPATH;
3135		if (tb[NHA_GROUP_TYPE])
3136			cfg->nh_grp_type = nla_get_u16(tb[NHA_GROUP_TYPE]);
3137
3138		if (cfg->nh_grp_type > NEXTHOP_GRP_TYPE_MAX) {
3139			NL_SET_ERR_MSG(extack, "Invalid group type");
3140			goto out;
3141		}
3142
3143		err = nh_check_attr_group(net, tb, ARRAY_SIZE(rtm_nh_policy_new),
3144					  cfg->nh_grp_type, extack);
3145		if (err)
3146			goto out;
3147
3148		if (cfg->nh_grp_type == NEXTHOP_GRP_TYPE_RES)
3149			err = rtm_to_nh_config_grp_res(tb[NHA_RES_GROUP],
3150						       cfg, extack);
3151
3152		if (tb[NHA_HW_STATS_ENABLE])
3153			cfg->nh_hw_stats = nla_get_u32(tb[NHA_HW_STATS_ENABLE]);
3154
3155		/* no other attributes should be set */
3156		goto out;
3157	}
3158
3159	if (tb[NHA_BLACKHOLE]) {
3160		if (tb[NHA_GATEWAY] || tb[NHA_OIF] ||
3161		    tb[NHA_ENCAP]   || tb[NHA_ENCAP_TYPE] || tb[NHA_FDB]) {
3162			NL_SET_ERR_MSG(extack, "Blackhole attribute can not be used with gateway, oif, encap or fdb");
3163			goto out;
3164		}
3165
3166		cfg->nh_blackhole = 1;
3167		err = 0;
3168		goto out;
3169	}
3170
3171	if (!cfg->nh_fdb && !tb[NHA_OIF]) {
3172		NL_SET_ERR_MSG(extack, "Device attribute required for non-blackhole and non-fdb nexthops");
3173		goto out;
3174	}
3175
3176	err = -EINVAL;
3177	if (tb[NHA_GATEWAY]) {
3178		struct nlattr *gwa = tb[NHA_GATEWAY];
3179
3180		switch (cfg->nh_family) {
3181		case AF_INET:
3182			if (nla_len(gwa) != sizeof(u32)) {
3183				NL_SET_ERR_MSG(extack, "Invalid gateway");
3184				goto out;
3185			}
3186			cfg->gw.ipv4 = nla_get_be32(gwa);
3187			break;
3188		case AF_INET6:
3189			if (nla_len(gwa) != sizeof(struct in6_addr)) {
3190				NL_SET_ERR_MSG(extack, "Invalid gateway");
3191				goto out;
3192			}
3193			cfg->gw.ipv6 = nla_get_in6_addr(gwa);
3194			break;
3195		default:
3196			NL_SET_ERR_MSG(extack,
3197				       "Unknown address family for gateway");
3198			goto out;
3199		}
3200	} else {
3201		/* device only nexthop (no gateway) */
3202		if (cfg->nh_flags & RTNH_F_ONLINK) {
3203			NL_SET_ERR_MSG(extack,
3204				       "ONLINK flag can not be set for nexthop without a gateway");
3205			goto out;
3206		}
3207	}
3208
3209	if (tb[NHA_ENCAP]) {
3210		cfg->nh_encap = tb[NHA_ENCAP];
3211
3212		if (!tb[NHA_ENCAP_TYPE]) {
3213			NL_SET_ERR_MSG(extack, "LWT encapsulation type is missing");
3214			goto out;
3215		}
3216
3217		cfg->nh_encap_type = nla_get_u16(tb[NHA_ENCAP_TYPE]);
3218		err = lwtunnel_valid_encap_type(cfg->nh_encap_type, extack);
3219		if (err < 0)
3220			goto out;
3221
3222	} else if (tb[NHA_ENCAP_TYPE]) {
3223		NL_SET_ERR_MSG(extack, "LWT encapsulation attribute is missing");
3224		goto out;
3225	}
3226
3227	if (tb[NHA_HW_STATS_ENABLE]) {
3228		NL_SET_ERR_MSG(extack, "Cannot enable nexthop hardware statistics for non-group nexthops");
3229		goto out;
3230	}
3231
3232	err = 0;
3233out:
3234	return err;
3235}
3236
3237static int rtm_to_nh_config_rtnl(struct net *net, struct nlattr **tb,
3238				 struct nh_config *cfg,
3239				 struct netlink_ext_ack *extack)
3240{
3241	if (tb[NHA_GROUP])
3242		return nh_check_attr_group_rtnl(net, tb, extack);
3243
3244	if (tb[NHA_OIF]) {
3245		cfg->nh_ifindex = nla_get_u32(tb[NHA_OIF]);
3246		if (cfg->nh_ifindex)
3247			cfg->dev = __dev_get_by_index(net, cfg->nh_ifindex);
3248
3249		if (!cfg->dev) {
3250			NL_SET_ERR_MSG(extack, "Invalid device index");
3251			return -EINVAL;
3252		}
3253
3254		if (!(cfg->dev->flags & IFF_UP)) {
3255			NL_SET_ERR_MSG(extack, "Nexthop device is not up");
3256			return -ENETDOWN;
3257		}
3258
3259		if (!netif_carrier_ok(cfg->dev)) {
3260			NL_SET_ERR_MSG(extack, "Carrier for nexthop device is down");
3261			return -ENETDOWN;
3262		}
3263	}
3264
3265	return 0;
3266}
3267
3268/* rtnl */
3269static int rtm_new_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,
3270			   struct netlink_ext_ack *extack)
3271{
3272	struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_new)];
3273	struct net *net = sock_net(skb->sk);
3274	struct nh_config cfg;
3275	struct nexthop *nh;
3276	int err;
3277
3278	err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
3279			  ARRAY_SIZE(rtm_nh_policy_new) - 1,
3280			  rtm_nh_policy_new, extack);
3281	if (err < 0)
3282		goto out;
3283
3284	err = rtm_to_nh_config(net, skb, nlh, tb, &cfg, extack);
3285	if (err)
3286		goto out;
3287
3288	if (cfg.nlflags & NLM_F_REPLACE && !cfg.nh_id) {
3289		NL_SET_ERR_MSG(extack, "Replace requires nexthop id");
3290		err = -EINVAL;
3291		goto out;
3292	}
3293
3294	rtnl_net_lock(net);
3295
3296	err = rtm_to_nh_config_rtnl(net, tb, &cfg, extack);
3297	if (err)
3298		goto unlock;
3299
3300	nh = nexthop_add(net, &cfg, extack);
3301	if (IS_ERR(nh))
3302		err = PTR_ERR(nh);
3303
3304unlock:
3305	rtnl_net_unlock(net);
3306out:
3307	return err;
3308}
3309
3310static int nh_valid_get_del_req(const struct nlmsghdr *nlh,
3311				struct nlattr **tb, u32 *id, u32 *op_flags,
3312				struct netlink_ext_ack *extack)
3313{
3314	struct nhmsg *nhm = nlmsg_data(nlh);
3315
3316	if (nhm->nh_protocol || nhm->resvd || nhm->nh_scope || nhm->nh_flags) {
3317		NL_SET_ERR_MSG(extack, "Invalid values in header");
3318		return -EINVAL;
3319	}
3320
3321	if (!tb[NHA_ID]) {
3322		NL_SET_ERR_MSG(extack, "Nexthop id is missing");
3323		return -EINVAL;
3324	}
3325
3326	*id = nla_get_u32(tb[NHA_ID]);
3327	if (!(*id)) {
3328		NL_SET_ERR_MSG(extack, "Invalid nexthop id");
3329		return -EINVAL;
3330	}
3331
3332	if (op_flags)
3333		*op_flags = nla_get_u32_default(tb[NHA_OP_FLAGS], 0);
3334
3335	return 0;
3336}
3337
3338/* rtnl */
3339static int rtm_del_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,
3340			   struct netlink_ext_ack *extack)
3341{
3342	struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_del)];
3343	struct net *net = sock_net(skb->sk);
3344	struct nl_info nlinfo = {
3345		.nlh = nlh,
3346		.nl_net = net,
3347		.portid = NETLINK_CB(skb).portid,
3348	};
3349	struct nexthop *nh;
3350	int err;
3351	u32 id;
3352
3353	err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
3354			  ARRAY_SIZE(rtm_nh_policy_del) - 1, rtm_nh_policy_del,
3355			  extack);
3356	if (err < 0)
3357		return err;
3358
3359	err = nh_valid_get_del_req(nlh, tb, &id, NULL, extack);
3360	if (err)
3361		return err;
3362
3363	rtnl_net_lock(net);
3364
3365	nh = nexthop_find_by_id(net, id);
3366	if (nh)
3367		remove_nexthop(net, nh, &nlinfo);
3368	else
3369		err = -ENOENT;
3370
3371	rtnl_net_unlock(net);
3372
3373	return err;
3374}
3375
3376/* rtnl */
3377static int rtm_get_nexthop(struct sk_buff *in_skb, struct nlmsghdr *nlh,
3378			   struct netlink_ext_ack *extack)
3379{
3380	struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_get)];
3381	struct net *net = sock_net(in_skb->sk);
3382	struct sk_buff *skb = NULL;
3383	struct nexthop *nh;
3384	u32 op_flags;
3385	int err;
3386	u32 id;
3387
3388	err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
3389			  ARRAY_SIZE(rtm_nh_policy_get) - 1, rtm_nh_policy_get,
3390			  extack);
3391	if (err < 0)
3392		return err;
3393
3394	err = nh_valid_get_del_req(nlh, tb, &id, &op_flags, extack);
3395	if (err)
3396		return err;
3397
3398	err = -ENOENT;
3399	nh = nexthop_find_by_id(net, id);
3400	if (!nh)
3401		goto out;
3402
3403	err = -ENOBUFS;
3404	skb = nlmsg_new(nh_nlmsg_size(nh, op_flags), GFP_KERNEL);
3405	if (!skb)
3406		goto out;
3407
3408	err = nh_fill_node(skb, nh, RTM_NEWNEXTHOP, NETLINK_CB(in_skb).portid,
3409			   nlh->nlmsg_seq, 0, op_flags);
3410	if (err < 0) {
3411		WARN_ON(err == -EMSGSIZE);
3412		goto errout_free;
3413	}
3414
3415	err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
3416out:
3417	return err;
3418errout_free:
3419	kfree_skb(skb);
3420	goto out;
3421}
3422
3423struct nh_dump_filter {
3424	u32 nh_id;
3425	int dev_idx;
3426	int master_idx;
3427	bool group_filter;
3428	bool fdb_filter;
3429	u32 res_bucket_nh_id;
3430	u32 op_flags;
3431};
3432
3433static bool nh_dump_filtered(struct nexthop *nh,
3434			     struct nh_dump_filter *filter, u8 family)
3435{
3436	const struct net_device *dev;
3437	const struct nh_info *nhi;
3438
3439	if (filter->group_filter && !nh->is_group)
3440		return true;
3441
3442	if (!filter->dev_idx && !filter->master_idx && !family)
3443		return false;
3444
3445	if (nh->is_group)
3446		return true;
3447
3448	nhi = rtnl_dereference(nh->nh_info);
3449	if (family && nhi->family != family)
3450		return true;
3451
3452	dev = nhi->fib_nhc.nhc_dev;
3453	if (filter->dev_idx && (!dev || dev->ifindex != filter->dev_idx))
3454		return true;
3455
3456	if (filter->master_idx) {
3457		struct net_device *master;
3458
3459		if (!dev)
3460			return true;
3461
3462		master = netdev_master_upper_dev_get((struct net_device *)dev);
3463		if (!master || master->ifindex != filter->master_idx)
3464			return true;
3465	}
3466
3467	return false;
3468}
3469
3470static int __nh_valid_dump_req(const struct nlmsghdr *nlh, struct nlattr **tb,
3471			       struct nh_dump_filter *filter,
3472			       struct netlink_ext_ack *extack)
3473{
3474	struct nhmsg *nhm;
3475	u32 idx;
3476
3477	if (tb[NHA_OIF]) {
3478		idx = nla_get_u32(tb[NHA_OIF]);
3479		if (idx > INT_MAX) {
3480			NL_SET_ERR_MSG(extack, "Invalid device index");
3481			return -EINVAL;
3482		}
3483		filter->dev_idx = idx;
3484	}
3485	if (tb[NHA_MASTER]) {
3486		idx = nla_get_u32(tb[NHA_MASTER]);
3487		if (idx > INT_MAX) {
3488			NL_SET_ERR_MSG(extack, "Invalid master device index");
3489			return -EINVAL;
3490		}
3491		filter->master_idx = idx;
3492	}
3493	filter->group_filter = nla_get_flag(tb[NHA_GROUPS]);
3494	filter->fdb_filter = nla_get_flag(tb[NHA_FDB]);
3495
3496	nhm = nlmsg_data(nlh);
3497	if (nhm->nh_protocol || nhm->resvd || nhm->nh_scope || nhm->nh_flags) {
3498		NL_SET_ERR_MSG(extack, "Invalid values in header for nexthop dump request");
3499		return -EINVAL;
3500	}
3501
3502	return 0;
3503}
3504
3505static int nh_valid_dump_req(const struct nlmsghdr *nlh,
3506			     struct nh_dump_filter *filter,
3507			     struct netlink_callback *cb)
3508{
3509	struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_dump)];
3510	int err;
3511
3512	err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
3513			  ARRAY_SIZE(rtm_nh_policy_dump) - 1,
3514			  rtm_nh_policy_dump, cb->extack);
3515	if (err < 0)
3516		return err;
3517
3518	filter->op_flags = nla_get_u32_default(tb[NHA_OP_FLAGS], 0);
3519
3520	return __nh_valid_dump_req(nlh, tb, filter, cb->extack);
3521}
3522
3523struct rtm_dump_nh_ctx {
3524	u32 idx;
3525};
3526
3527static struct rtm_dump_nh_ctx *
3528rtm_dump_nh_ctx(struct netlink_callback *cb)
3529{
3530	struct rtm_dump_nh_ctx *ctx = (void *)cb->ctx;
3531
3532	BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
3533	return ctx;
3534}
3535
3536static int rtm_dump_walk_nexthops(struct sk_buff *skb,
3537				  struct netlink_callback *cb,
3538				  struct rb_root *root,
3539				  struct rtm_dump_nh_ctx *ctx,
3540				  int (*nh_cb)(struct sk_buff *skb,
3541					       struct netlink_callback *cb,
3542					       struct nexthop *nh, void *data),
3543				  void *data)
3544{
3545	struct rb_node *node;
3546	int s_idx;
3547	int err;
3548
3549	s_idx = ctx->idx;
3550
3551	/* If this is not the first invocation, ctx->idx will contain the id of
3552	 * the last nexthop we processed. Instead of starting from the very
3553	 * first element of the red/black tree again and linearly skipping the
3554	 * (potentially large) set of nodes with an id smaller than s_idx, walk
3555	 * the tree and find the left-most node whose id is >= s_idx.  This
3556	 * provides an efficient O(log n) starting point for the dump
3557	 * continuation.
3558	 */
3559	if (s_idx != 0) {
3560		struct rb_node *tmp = root->rb_node;
3561
3562		node = NULL;
3563		while (tmp) {
3564			struct nexthop *nh;
3565
3566			nh = rb_entry(tmp, struct nexthop, rb_node);
3567			if (nh->id < s_idx) {
3568				tmp = tmp->rb_right;
3569			} else {
3570				/* Track current candidate and keep looking on
3571				 * the left side to find the left-most
3572				 * (smallest id) that is still >= s_idx.
3573				 */
3574				node = tmp;
3575				tmp = tmp->rb_left;
3576			}
3577		}
3578	} else {
3579		node = rb_first(root);
3580	}
3581
3582	for (; node; node = rb_next(node)) {
3583		struct nexthop *nh;
3584
3585		nh = rb_entry(node, struct nexthop, rb_node);
3586
3587		ctx->idx = nh->id;
3588		err = nh_cb(skb, cb, nh, data);
3589		if (err)
3590			return err;
3591	}
3592
3593	return 0;
3594}
3595
3596static int rtm_dump_nexthop_cb(struct sk_buff *skb, struct netlink_callback *cb,
3597			       struct nexthop *nh, void *data)
3598{
3599	struct nhmsg *nhm = nlmsg_data(cb->nlh);
3600	struct nh_dump_filter *filter = data;
3601
3602	if (nh_dump_filtered(nh, filter, nhm->nh_family))
3603		return 0;
3604
3605	return nh_fill_node(skb, nh, RTM_NEWNEXTHOP,
3606			    NETLINK_CB(cb->skb).portid,
3607			    cb->nlh->nlmsg_seq, NLM_F_MULTI, filter->op_flags);
3608}
3609
3610/* rtnl */
3611static int rtm_dump_nexthop(struct sk_buff *skb, struct netlink_callback *cb)
3612{
3613	struct rtm_dump_nh_ctx *ctx = rtm_dump_nh_ctx(cb);
3614	struct net *net = sock_net(skb->sk);
3615	struct rb_root *root = &net->nexthop.rb_root;
3616	struct nh_dump_filter filter = {};
3617	int err;
3618
3619	err = nh_valid_dump_req(cb->nlh, &filter, cb);
3620	if (err < 0)
3621		return err;
3622
3623	err = rtm_dump_walk_nexthops(skb, cb, root, ctx,
3624				     &rtm_dump_nexthop_cb, &filter);
3625
3626	cb->seq = net->nexthop.seq;
3627	nl_dump_check_consistent(cb, nlmsg_hdr(skb));
3628	return err;
3629}
3630
3631static struct nexthop *
3632nexthop_find_group_resilient(struct net *net, u32 id,
3633			     struct netlink_ext_ack *extack)
3634{
3635	struct nh_group *nhg;
3636	struct nexthop *nh;
3637
3638	nh = nexthop_find_by_id(net, id);
3639	if (!nh)
3640		return ERR_PTR(-ENOENT);
3641
3642	if (!nh->is_group) {
3643		NL_SET_ERR_MSG(extack, "Not a nexthop group");
3644		return ERR_PTR(-EINVAL);
3645	}
3646
3647	nhg = rtnl_dereference(nh->nh_grp);
3648	if (!nhg->resilient) {
3649		NL_SET_ERR_MSG(extack, "Nexthop group not of type resilient");
3650		return ERR_PTR(-EINVAL);
3651	}
3652
3653	return nh;
3654}
3655
3656static int nh_valid_dump_nhid(struct nlattr *attr, u32 *nh_id_p,
3657			      struct netlink_ext_ack *extack)
3658{
3659	u32 idx;
3660
3661	if (attr) {
3662		idx = nla_get_u32(attr);
3663		if (!idx) {
3664			NL_SET_ERR_MSG(extack, "Invalid nexthop id");
3665			return -EINVAL;
3666		}
3667		*nh_id_p = idx;
3668	} else {
3669		*nh_id_p = 0;
3670	}
3671
3672	return 0;
3673}
3674
3675static int nh_valid_dump_bucket_req(const struct nlmsghdr *nlh,
3676				    struct nh_dump_filter *filter,
3677				    struct netlink_callback *cb)
3678{
3679	struct nlattr *res_tb[ARRAY_SIZE(rtm_nh_res_bucket_policy_dump)];
3680	struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_dump_bucket)];
3681	int err;
3682
3683	err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
3684			  ARRAY_SIZE(rtm_nh_policy_dump_bucket) - 1,
3685			  rtm_nh_policy_dump_bucket, NULL);
3686	if (err < 0)
3687		return err;
3688
3689	err = nh_valid_dump_nhid(tb[NHA_ID], &filter->nh_id, cb->extack);
3690	if (err)
3691		return err;
3692
3693	if (tb[NHA_RES_BUCKET]) {
3694		size_t max = ARRAY_SIZE(rtm_nh_res_bucket_policy_dump) - 1;
3695
3696		err = nla_parse_nested(res_tb, max,
3697				       tb[NHA_RES_BUCKET],
3698				       rtm_nh_res_bucket_policy_dump,
3699				       cb->extack);
3700		if (err < 0)
3701			return err;
3702
3703		err = nh_valid_dump_nhid(res_tb[NHA_RES_BUCKET_NH_ID],
3704					 &filter->res_bucket_nh_id,
3705					 cb->extack);
3706		if (err)
3707			return err;
3708	}
3709
3710	return __nh_valid_dump_req(nlh, tb, filter, cb->extack);
3711}
3712
3713struct rtm_dump_res_bucket_ctx {
3714	struct rtm_dump_nh_ctx nh;
3715	u16 bucket_index;
3716};
3717
3718static struct rtm_dump_res_bucket_ctx *
3719rtm_dump_res_bucket_ctx(struct netlink_callback *cb)
3720{
3721	struct rtm_dump_res_bucket_ctx *ctx = (void *)cb->ctx;
3722
3723	BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
3724	return ctx;
3725}
3726
3727struct rtm_dump_nexthop_bucket_data {
3728	struct rtm_dump_res_bucket_ctx *ctx;
3729	struct nh_dump_filter filter;
3730};
3731
3732static int rtm_dump_nexthop_bucket_nh(struct sk_buff *skb,
3733				      struct netlink_callback *cb,
3734				      struct nexthop *nh,
3735				      struct rtm_dump_nexthop_bucket_data *dd)
3736{
3737	u32 portid = NETLINK_CB(cb->skb).portid;
3738	struct nhmsg *nhm = nlmsg_data(cb->nlh);
3739	struct nh_res_table *res_table;
3740	struct nh_group *nhg;
3741	u16 bucket_index;
3742	int err;
3743
3744	nhg = rtnl_dereference(nh->nh_grp);
3745	res_table = rtnl_dereference(nhg->res_table);
3746	for (bucket_index = dd->ctx->bucket_index;
3747	     bucket_index < res_table->num_nh_buckets;
3748	     bucket_index++) {
3749		struct nh_res_bucket *bucket;
3750		struct nh_grp_entry *nhge;
3751
3752		bucket = &res_table->nh_buckets[bucket_index];
3753		nhge = rtnl_dereference(bucket->nh_entry);
3754		if (nh_dump_filtered(nhge->nh, &dd->filter, nhm->nh_family))
3755			continue;
3756
3757		if (dd->filter.res_bucket_nh_id &&
3758		    dd->filter.res_bucket_nh_id != nhge->nh->id)
3759			continue;
3760
3761		dd->ctx->bucket_index = bucket_index;
3762		err = nh_fill_res_bucket(skb, nh, bucket, bucket_index,
3763					 RTM_NEWNEXTHOPBUCKET, portid,
3764					 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3765					 cb->extack);
3766		if (err)
3767			return err;
3768	}
3769
3770	dd->ctx->bucket_index = 0;
3771
3772	return 0;
3773}
3774
3775static int rtm_dump_nexthop_bucket_cb(struct sk_buff *skb,
3776				      struct netlink_callback *cb,
3777				      struct nexthop *nh, void *data)
3778{
3779	struct rtm_dump_nexthop_bucket_data *dd = data;
3780	struct nh_group *nhg;
3781
3782	if (!nh->is_group)
3783		return 0;
3784
3785	nhg = rtnl_dereference(nh->nh_grp);
3786	if (!nhg->resilient)
3787		return 0;
3788
3789	return rtm_dump_nexthop_bucket_nh(skb, cb, nh, dd);
3790}
3791
3792/* rtnl */
3793static int rtm_dump_nexthop_bucket(struct sk_buff *skb,
3794				   struct netlink_callback *cb)
3795{
3796	struct rtm_dump_res_bucket_ctx *ctx = rtm_dump_res_bucket_ctx(cb);
3797	struct rtm_dump_nexthop_bucket_data dd = { .ctx = ctx };
3798	struct net *net = sock_net(skb->sk);
3799	struct nexthop *nh;
3800	int err;
3801
3802	err = nh_valid_dump_bucket_req(cb->nlh, &dd.filter, cb);
3803	if (err)
3804		return err;
3805
3806	if (dd.filter.nh_id) {
3807		nh = nexthop_find_group_resilient(net, dd.filter.nh_id,
3808						  cb->extack);
3809		if (IS_ERR(nh))
3810			return PTR_ERR(nh);
3811		err = rtm_dump_nexthop_bucket_nh(skb, cb, nh, &dd);
3812	} else {
3813		struct rb_root *root = &net->nexthop.rb_root;
3814
3815		err = rtm_dump_walk_nexthops(skb, cb, root, &ctx->nh,
3816					     &rtm_dump_nexthop_bucket_cb, &dd);
3817	}
3818
3819	cb->seq = net->nexthop.seq;
3820	nl_dump_check_consistent(cb, nlmsg_hdr(skb));
3821	return err;
3822}
3823
3824static int nh_valid_get_bucket_req_res_bucket(struct nlattr *res,
3825					      u16 *bucket_index,
3826					      struct netlink_ext_ack *extack)
3827{
3828	struct nlattr *tb[ARRAY_SIZE(rtm_nh_res_bucket_policy_get)];
3829	int err;
3830
3831	err = nla_parse_nested(tb, ARRAY_SIZE(rtm_nh_res_bucket_policy_get) - 1,
3832			       res, rtm_nh_res_bucket_policy_get, extack);
3833	if (err < 0)
3834		return err;
3835
3836	if (!tb[NHA_RES_BUCKET_INDEX]) {
3837		NL_SET_ERR_MSG(extack, "Bucket index is missing");
3838		return -EINVAL;
3839	}
3840
3841	*bucket_index = nla_get_u16(tb[NHA_RES_BUCKET_INDEX]);
3842	return 0;
3843}
3844
3845static int nh_valid_get_bucket_req(const struct nlmsghdr *nlh,
3846				   u32 *id, u16 *bucket_index,
3847				   struct netlink_ext_ack *extack)
3848{
3849	struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_get_bucket)];
3850	int err;
3851
3852	err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
3853			  ARRAY_SIZE(rtm_nh_policy_get_bucket) - 1,
3854			  rtm_nh_policy_get_bucket, extack);
3855	if (err < 0)
3856		return err;
3857
3858	err = nh_valid_get_del_req(nlh, tb, id, NULL, extack);
3859	if (err)
3860		return err;
3861
3862	if (!tb[NHA_RES_BUCKET]) {
3863		NL_SET_ERR_MSG(extack, "Bucket information is missing");
3864		return -EINVAL;
3865	}
3866
3867	err = nh_valid_get_bucket_req_res_bucket(tb[NHA_RES_BUCKET],
3868						 bucket_index, extack);
3869	if (err)
3870		return err;
3871
3872	return 0;
3873}
3874
3875/* rtnl */
3876static int rtm_get_nexthop_bucket(struct sk_buff *in_skb, struct nlmsghdr *nlh,
3877				  struct netlink_ext_ack *extack)
3878{
3879	struct net *net = sock_net(in_skb->sk);
3880	struct nh_res_table *res_table;
3881	struct sk_buff *skb = NULL;
3882	struct nh_group *nhg;
3883	struct nexthop *nh;
3884	u16 bucket_index;
3885	int err;
3886	u32 id;
3887
3888	err = nh_valid_get_bucket_req(nlh, &id, &bucket_index, extack);
3889	if (err)
3890		return err;
3891
3892	nh = nexthop_find_group_resilient(net, id, extack);
3893	if (IS_ERR(nh))
3894		return PTR_ERR(nh);
3895
3896	nhg = rtnl_dereference(nh->nh_grp);
3897	res_table = rtnl_dereference(nhg->res_table);
3898	if (bucket_index >= res_table->num_nh_buckets) {
3899		NL_SET_ERR_MSG(extack, "Bucket index out of bounds");
3900		return -ENOENT;
3901	}
3902
3903	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
3904	if (!skb)
3905		return -ENOBUFS;
3906
3907	err = nh_fill_res_bucket(skb, nh, &res_table->nh_buckets[bucket_index],
3908				 bucket_index, RTM_NEWNEXTHOPBUCKET,
3909				 NETLINK_CB(in_skb).portid, nlh->nlmsg_seq,
3910				 0, extack);
3911	if (err < 0) {
3912		WARN_ON(err == -EMSGSIZE);
3913		goto errout_free;
3914	}
3915
3916	return rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
3917
3918errout_free:
3919	kfree_skb(skb);
3920	return err;
3921}
3922
3923static void nexthop_sync_mtu(struct net_device *dev, u32 orig_mtu)
3924{
3925	unsigned int hash = nh_dev_hashfn(dev->ifindex);
3926	struct net *net = dev_net(dev);
3927	struct hlist_head *head = &net->nexthop.devhash[hash];
3928	struct hlist_node *n;
3929	struct nh_info *nhi;
3930
3931	hlist_for_each_entry_safe(nhi, n, head, dev_hash) {
3932		if (nhi->fib_nhc.nhc_dev == dev) {
3933			if (nhi->family == AF_INET)
3934				fib_nhc_update_mtu(&nhi->fib_nhc, dev->mtu,
3935						   orig_mtu);
3936		}
3937	}
3938}
3939
3940/* rtnl */
3941static int nh_netdev_event(struct notifier_block *this,
3942			   unsigned long event, void *ptr)
3943{
3944	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
3945	struct netdev_notifier_info_ext *info_ext;
3946
3947	switch (event) {
3948	case NETDEV_DOWN:
3949	case NETDEV_UNREGISTER:
3950		nexthop_flush_dev(dev, event);
3951		break;
3952	case NETDEV_CHANGE:
3953		if (!(netif_get_flags(dev) & (IFF_RUNNING | IFF_LOWER_UP)))
3954			nexthop_flush_dev(dev, event);
3955		break;
3956	case NETDEV_CHANGEMTU:
3957		info_ext = ptr;
3958		nexthop_sync_mtu(dev, info_ext->ext.mtu);
3959		rt_cache_flush(dev_net(dev));
3960		break;
3961	}
3962	return NOTIFY_DONE;
3963}
3964
3965static struct notifier_block nh_netdev_notifier = {
3966	.notifier_call = nh_netdev_event,
3967};
3968
3969static int nexthops_dump(struct net *net, struct notifier_block *nb,
3970			 enum nexthop_event_type event_type,
3971			 struct netlink_ext_ack *extack)
3972{
3973	struct rb_root *root = &net->nexthop.rb_root;
3974	struct rb_node *node;
3975	int err = 0;
3976
3977	for (node = rb_first(root); node; node = rb_next(node)) {
3978		struct nexthop *nh;
3979
3980		nh = rb_entry(node, struct nexthop, rb_node);
3981		err = call_nexthop_notifier(nb, net, event_type, nh, extack);
3982		if (err)
3983			break;
3984	}
3985
3986	return err;
3987}
3988
3989int register_nexthop_notifier(struct net *net, struct notifier_block *nb,
3990			      struct netlink_ext_ack *extack)
3991{
3992	int err;
3993
3994	rtnl_lock();
3995	err = nexthops_dump(net, nb, NEXTHOP_EVENT_REPLACE, extack);
3996	if (err)
3997		goto unlock;
3998	err = blocking_notifier_chain_register(&net->nexthop.notifier_chain,
3999					       nb);
4000unlock:
4001	rtnl_unlock();
4002	return err;
4003}
4004EXPORT_SYMBOL(register_nexthop_notifier);
4005
4006int __unregister_nexthop_notifier(struct net *net, struct notifier_block *nb)
4007{
4008	int err;
4009
4010	err = blocking_notifier_chain_unregister(&net->nexthop.notifier_chain,
4011						 nb);
4012	if (!err)
4013		nexthops_dump(net, nb, NEXTHOP_EVENT_DEL, NULL);
4014	return err;
4015}
4016EXPORT_SYMBOL(__unregister_nexthop_notifier);
4017
4018int unregister_nexthop_notifier(struct net *net, struct notifier_block *nb)
4019{
4020	int err;
4021
4022	rtnl_lock();
4023	err = __unregister_nexthop_notifier(net, nb);
4024	rtnl_unlock();
4025	return err;
4026}
4027EXPORT_SYMBOL(unregister_nexthop_notifier);
4028
4029void nexthop_set_hw_flags(struct net *net, u32 id, bool offload, bool trap)
4030{
4031	struct nexthop *nexthop;
4032
4033	rcu_read_lock();
4034
4035	nexthop = nexthop_find_by_id(net, id);
4036	if (!nexthop)
4037		goto out;
4038
4039	nexthop->nh_flags &= ~(RTNH_F_OFFLOAD | RTNH_F_TRAP);
4040	if (offload)
4041		nexthop->nh_flags |= RTNH_F_OFFLOAD;
4042	if (trap)
4043		nexthop->nh_flags |= RTNH_F_TRAP;
4044
4045out:
4046	rcu_read_unlock();
4047}
4048EXPORT_SYMBOL(nexthop_set_hw_flags);
4049
4050void nexthop_bucket_set_hw_flags(struct net *net, u32 id, u16 bucket_index,
4051				 bool offload, bool trap)
4052{
4053	struct nh_res_table *res_table;
4054	struct nh_res_bucket *bucket;
4055	struct nexthop *nexthop;
4056	struct nh_group *nhg;
4057
4058	rcu_read_lock();
4059
4060	nexthop = nexthop_find_by_id(net, id);
4061	if (!nexthop || !nexthop->is_group)
4062		goto out;
4063
4064	nhg = rcu_dereference(nexthop->nh_grp);
4065	if (!nhg->resilient)
4066		goto out;
4067
4068	if (bucket_index >= nhg->res_table->num_nh_buckets)
4069		goto out;
4070
4071	res_table = rcu_dereference(nhg->res_table);
4072	bucket = &res_table->nh_buckets[bucket_index];
4073	bucket->nh_flags &= ~(RTNH_F_OFFLOAD | RTNH_F_TRAP);
4074	if (offload)
4075		bucket->nh_flags |= RTNH_F_OFFLOAD;
4076	if (trap)
4077		bucket->nh_flags |= RTNH_F_TRAP;
4078
4079out:
4080	rcu_read_unlock();
4081}
4082EXPORT_SYMBOL(nexthop_bucket_set_hw_flags);
4083
4084void nexthop_res_grp_activity_update(struct net *net, u32 id, u16 num_buckets,
4085				     unsigned long *activity)
4086{
4087	struct nh_res_table *res_table;
4088	struct nexthop *nexthop;
4089	struct nh_group *nhg;
4090	u16 i;
4091
4092	rcu_read_lock();
4093
4094	nexthop = nexthop_find_by_id(net, id);
4095	if (!nexthop || !nexthop->is_group)
4096		goto out;
4097
4098	nhg = rcu_dereference(nexthop->nh_grp);
4099	if (!nhg->resilient)
4100		goto out;
4101
4102	/* Instead of silently ignoring some buckets, demand that the sizes
4103	 * be the same.
4104	 */
4105	res_table = rcu_dereference(nhg->res_table);
4106	if (num_buckets != res_table->num_nh_buckets)
4107		goto out;
4108
4109	for (i = 0; i < num_buckets; i++) {
4110		if (test_bit(i, activity))
4111			nh_res_bucket_set_busy(&res_table->nh_buckets[i]);
4112	}
4113
4114out:
4115	rcu_read_unlock();
4116}
4117EXPORT_SYMBOL(nexthop_res_grp_activity_update);
4118
4119static void __net_exit nexthop_net_exit_rtnl(struct net *net,
4120					     struct list_head *dev_to_kill)
4121{
4122	ASSERT_RTNL_NET(net);
4123	flush_all_nexthops(net);
4124}
4125
4126static void __net_exit nexthop_net_exit(struct net *net)
4127{
4128	kfree(net->nexthop.devhash);
4129	net->nexthop.devhash = NULL;
4130}
4131
4132static int __net_init nexthop_net_init(struct net *net)
4133{
4134	size_t sz = sizeof(struct hlist_head) * NH_DEV_HASHSIZE;
4135
4136	net->nexthop.rb_root = RB_ROOT;
4137	net->nexthop.devhash = kzalloc(sz, GFP_KERNEL);
4138	if (!net->nexthop.devhash)
4139		return -ENOMEM;
4140	BLOCKING_INIT_NOTIFIER_HEAD(&net->nexthop.notifier_chain);
4141
4142	return 0;
4143}
4144
4145static struct pernet_operations nexthop_net_ops = {
4146	.init = nexthop_net_init,
4147	.exit = nexthop_net_exit,
4148	.exit_rtnl = nexthop_net_exit_rtnl,
4149};
4150
4151static const struct rtnl_msg_handler nexthop_rtnl_msg_handlers[] __initconst = {
4152	{.msgtype = RTM_NEWNEXTHOP, .doit = rtm_new_nexthop,
4153	 .flags = RTNL_FLAG_DOIT_PERNET},
4154	{.msgtype = RTM_DELNEXTHOP, .doit = rtm_del_nexthop,
4155	 .flags = RTNL_FLAG_DOIT_PERNET},
4156	{.msgtype = RTM_GETNEXTHOP, .doit = rtm_get_nexthop,
4157	 .dumpit = rtm_dump_nexthop},
4158	{.msgtype = RTM_GETNEXTHOPBUCKET, .doit = rtm_get_nexthop_bucket,
4159	 .dumpit = rtm_dump_nexthop_bucket},
4160	{.protocol = PF_INET, .msgtype = RTM_NEWNEXTHOP,
4161	 .doit = rtm_new_nexthop, .flags = RTNL_FLAG_DOIT_PERNET},
4162	{.protocol = PF_INET, .msgtype = RTM_GETNEXTHOP,
4163	 .dumpit = rtm_dump_nexthop},
4164	{.protocol = PF_INET6, .msgtype = RTM_NEWNEXTHOP,
4165	 .doit = rtm_new_nexthop, .flags = RTNL_FLAG_DOIT_PERNET},
4166	{.protocol = PF_INET6, .msgtype = RTM_GETNEXTHOP,
4167	 .dumpit = rtm_dump_nexthop},
4168};
4169
4170static int __init nexthop_init(void)
4171{
4172	register_pernet_subsys(&nexthop_net_ops);
4173
4174	register_netdevice_notifier(&nh_netdev_notifier);
4175
4176	rtnl_register_many(nexthop_rtnl_msg_handlers);
4177
4178	return 0;
4179}
4180subsys_initcall(nexthop_init);
~/ Read-only file preview.