File Index
Files and directories
Sign in
FILE

spectrum_router.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c C
    1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
    2/* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */
    3
    4#include <linux/kernel.h>
    5#include <linux/types.h>
    6#include <linux/rhashtable.h>
    7#include <linux/bitops.h>
    8#include <linux/in6.h>
    9#include <linux/notifier.h>
   10#include <linux/inetdevice.h>
   11#include <linux/netdevice.h>
   12#include <linux/if_bridge.h>
   13#include <linux/socket.h>
   14#include <linux/route.h>
   15#include <linux/gcd.h>
   16#include <linux/if_macvlan.h>
   17#include <linux/refcount.h>
   18#include <linux/jhash.h>
   19#include <linux/net_namespace.h>
   20#include <linux/mutex.h>
   21#include <linux/genalloc.h>
   22#include <linux/xarray.h>
   23#include <net/netevent.h>
   24#include <net/neighbour.h>
   25#include <net/arp.h>
   26#include <net/inet_dscp.h>
   27#include <net/ip_fib.h>
   28#include <net/ip6_fib.h>
   29#include <net/nexthop.h>
   30#include <net/fib_rules.h>
   31#include <net/ip_tunnels.h>
   32#include <net/l3mdev.h>
   33#include <net/addrconf.h>
   34#include <net/ndisc.h>
   35#include <net/ipv6.h>
   36#include <net/fib_notifier.h>
   37#include <net/switchdev.h>
   38
   39#include "spectrum.h"
   40#include "core.h"
   41#include "reg.h"
   42#include "spectrum_cnt.h"
   43#include "spectrum_dpipe.h"
   44#include "spectrum_ipip.h"
   45#include "spectrum_mr.h"
   46#include "spectrum_mr_tcam.h"
   47#include "spectrum_router.h"
   48#include "spectrum_span.h"
   49
   50struct mlxsw_sp_fib;
   51struct mlxsw_sp_vr;
   52struct mlxsw_sp_lpm_tree;
   53struct mlxsw_sp_rif_ops;
   54
   55struct mlxsw_sp_crif_key {
   56	struct net_device *dev;
   57};
   58
   59struct mlxsw_sp_crif {
   60	struct mlxsw_sp_crif_key key;
   61	struct rhash_head ht_node;
   62	bool can_destroy;
   63	struct list_head nexthop_list;
   64	struct mlxsw_sp_rif *rif;
   65};
   66
   67static const struct rhashtable_params mlxsw_sp_crif_ht_params = {
   68	.key_offset = offsetof(struct mlxsw_sp_crif, key),
   69	.key_len = sizeof_field(struct mlxsw_sp_crif, key),
   70	.head_offset = offsetof(struct mlxsw_sp_crif, ht_node),
   71};
   72
   73struct mlxsw_sp_rif {
   74	struct mlxsw_sp_crif *crif; /* NULL for underlay RIF */
   75	netdevice_tracker dev_tracker;
   76	struct list_head neigh_list;
   77	struct mlxsw_sp_fid *fid;
   78	unsigned char addr[ETH_ALEN];
   79	int mtu;
   80	u16 rif_index;
   81	u8 mac_profile_id;
   82	u8 rif_entries;
   83	u16 vr_id;
   84	const struct mlxsw_sp_rif_ops *ops;
   85	struct mlxsw_sp *mlxsw_sp;
   86
   87	unsigned int counter_ingress;
   88	bool counter_ingress_valid;
   89	unsigned int counter_egress;
   90	bool counter_egress_valid;
   91};
   92
   93static struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif)
   94{
   95	if (!rif->crif)
   96		return NULL;
   97	return rif->crif->key.dev;
   98}
   99
  100struct mlxsw_sp_rif_params {
  101	struct net_device *dev;
  102	union {
  103		u16 system_port;
  104		u16 lag_id;
  105	};
  106	u16 vid;
  107	bool lag;
  108	bool double_entry;
  109};
  110
  111struct mlxsw_sp_rif_subport {
  112	struct mlxsw_sp_rif common;
  113	refcount_t ref_count;
  114	union {
  115		u16 system_port;
  116		u16 lag_id;
  117	};
  118	u16 vid;
  119	bool lag;
  120};
  121
  122struct mlxsw_sp_rif_ipip_lb {
  123	struct mlxsw_sp_rif common;
  124	struct mlxsw_sp_rif_ipip_lb_config lb_config;
  125	u16 ul_vr_id;	/* Spectrum-1. */
  126	u16 ul_rif_id;	/* Spectrum-2+. */
  127};
  128
  129struct mlxsw_sp_rif_params_ipip_lb {
  130	struct mlxsw_sp_rif_params common;
  131	struct mlxsw_sp_rif_ipip_lb_config lb_config;
  132};
  133
  134struct mlxsw_sp_rif_ops {
  135	enum mlxsw_sp_rif_type type;
  136	size_t rif_size;
  137
  138	void (*setup)(struct mlxsw_sp_rif *rif,
  139		      const struct mlxsw_sp_rif_params *params);
  140	int (*configure)(struct mlxsw_sp_rif *rif,
  141			 struct netlink_ext_ack *extack);
  142	void (*deconfigure)(struct mlxsw_sp_rif *rif);
  143	struct mlxsw_sp_fid * (*fid_get)(struct mlxsw_sp_rif *rif,
  144					 const struct mlxsw_sp_rif_params *params,
  145					 struct netlink_ext_ack *extack);
  146	void (*fdb_del)(struct mlxsw_sp_rif *rif, const char *mac);
  147};
  148
  149struct mlxsw_sp_rif_mac_profile {
  150	unsigned char mac_prefix[ETH_ALEN];
  151	refcount_t ref_count;
  152	u8 id;
  153};
  154
  155struct mlxsw_sp_router_ops {
  156	int (*init)(struct mlxsw_sp *mlxsw_sp);
  157	int (*ipips_init)(struct mlxsw_sp *mlxsw_sp);
  158};
  159
  160static struct mlxsw_sp_rif *
  161mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
  162			 const struct net_device *dev);
  163static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif);
  164static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree);
  165static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
  166				  struct mlxsw_sp_lpm_tree *lpm_tree);
  167static int mlxsw_sp_vr_lpm_tree_bind(struct mlxsw_sp *mlxsw_sp,
  168				     const struct mlxsw_sp_fib *fib,
  169				     u8 tree_id);
  170static int mlxsw_sp_vr_lpm_tree_unbind(struct mlxsw_sp *mlxsw_sp,
  171				       const struct mlxsw_sp_fib *fib);
  172
  173static unsigned int *
  174mlxsw_sp_rif_p_counter_get(struct mlxsw_sp_rif *rif,
  175			   enum mlxsw_sp_rif_counter_dir dir)
  176{
  177	switch (dir) {
  178	case MLXSW_SP_RIF_COUNTER_EGRESS:
  179		return &rif->counter_egress;
  180	case MLXSW_SP_RIF_COUNTER_INGRESS:
  181		return &rif->counter_ingress;
  182	}
  183	return NULL;
  184}
  185
  186static bool
  187mlxsw_sp_rif_counter_valid_get(struct mlxsw_sp_rif *rif,
  188			       enum mlxsw_sp_rif_counter_dir dir)
  189{
  190	switch (dir) {
  191	case MLXSW_SP_RIF_COUNTER_EGRESS:
  192		return rif->counter_egress_valid;
  193	case MLXSW_SP_RIF_COUNTER_INGRESS:
  194		return rif->counter_ingress_valid;
  195	}
  196	return false;
  197}
  198
  199static void
  200mlxsw_sp_rif_counter_valid_set(struct mlxsw_sp_rif *rif,
  201			       enum mlxsw_sp_rif_counter_dir dir,
  202			       bool valid)
  203{
  204	switch (dir) {
  205	case MLXSW_SP_RIF_COUNTER_EGRESS:
  206		rif->counter_egress_valid = valid;
  207		break;
  208	case MLXSW_SP_RIF_COUNTER_INGRESS:
  209		rif->counter_ingress_valid = valid;
  210		break;
  211	}
  212}
  213
  214static int mlxsw_sp_rif_counter_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
  215				     unsigned int counter_index, bool enable,
  216				     enum mlxsw_sp_rif_counter_dir dir)
  217{
  218	char ritr_pl[MLXSW_REG_RITR_LEN];
  219	bool is_egress = false;
  220	int err;
  221
  222	if (dir == MLXSW_SP_RIF_COUNTER_EGRESS)
  223		is_egress = true;
  224	mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
  225	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
  226	if (err)
  227		return err;
  228
  229	mlxsw_reg_ritr_counter_pack(ritr_pl, counter_index, enable,
  230				    is_egress);
  231	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
  232}
  233
  234int mlxsw_sp_rif_counter_value_get(struct mlxsw_sp *mlxsw_sp,
  235				   struct mlxsw_sp_rif *rif,
  236				   enum mlxsw_sp_rif_counter_dir dir, u64 *cnt)
  237{
  238	char ricnt_pl[MLXSW_REG_RICNT_LEN];
  239	unsigned int *p_counter_index;
  240	bool valid;
  241	int err;
  242
  243	valid = mlxsw_sp_rif_counter_valid_get(rif, dir);
  244	if (!valid)
  245		return -EINVAL;
  246
  247	p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
  248	if (!p_counter_index)
  249		return -EINVAL;
  250	mlxsw_reg_ricnt_pack(ricnt_pl, *p_counter_index,
  251			     MLXSW_REG_RICNT_OPCODE_NOP);
  252	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl);
  253	if (err)
  254		return err;
  255	*cnt = mlxsw_reg_ricnt_good_unicast_packets_get(ricnt_pl);
  256	return 0;
  257}
  258
  259struct mlxsw_sp_rif_counter_set_basic {
  260	u64 good_unicast_packets;
  261	u64 good_multicast_packets;
  262	u64 good_broadcast_packets;
  263	u64 good_unicast_bytes;
  264	u64 good_multicast_bytes;
  265	u64 good_broadcast_bytes;
  266	u64 error_packets;
  267	u64 discard_packets;
  268	u64 error_bytes;
  269	u64 discard_bytes;
  270};
  271
  272static int
  273mlxsw_sp_rif_counter_fetch_clear(struct mlxsw_sp_rif *rif,
  274				 enum mlxsw_sp_rif_counter_dir dir,
  275				 struct mlxsw_sp_rif_counter_set_basic *set)
  276{
  277	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
  278	char ricnt_pl[MLXSW_REG_RICNT_LEN];
  279	unsigned int *p_counter_index;
  280	int err;
  281
  282	if (!mlxsw_sp_rif_counter_valid_get(rif, dir))
  283		return -EINVAL;
  284
  285	p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
  286	if (!p_counter_index)
  287		return -EINVAL;
  288
  289	mlxsw_reg_ricnt_pack(ricnt_pl, *p_counter_index,
  290			     MLXSW_REG_RICNT_OPCODE_CLEAR);
  291	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl);
  292	if (err)
  293		return err;
  294
  295	if (!set)
  296		return 0;
  297
  298#define MLXSW_SP_RIF_COUNTER_EXTRACT(NAME)				\
  299		(set->NAME = mlxsw_reg_ricnt_ ## NAME ## _get(ricnt_pl))
  300
  301	MLXSW_SP_RIF_COUNTER_EXTRACT(good_unicast_packets);
  302	MLXSW_SP_RIF_COUNTER_EXTRACT(good_multicast_packets);
  303	MLXSW_SP_RIF_COUNTER_EXTRACT(good_broadcast_packets);
  304	MLXSW_SP_RIF_COUNTER_EXTRACT(good_unicast_bytes);
  305	MLXSW_SP_RIF_COUNTER_EXTRACT(good_multicast_bytes);
  306	MLXSW_SP_RIF_COUNTER_EXTRACT(good_broadcast_bytes);
  307	MLXSW_SP_RIF_COUNTER_EXTRACT(error_packets);
  308	MLXSW_SP_RIF_COUNTER_EXTRACT(discard_packets);
  309	MLXSW_SP_RIF_COUNTER_EXTRACT(error_bytes);
  310	MLXSW_SP_RIF_COUNTER_EXTRACT(discard_bytes);
  311
  312#undef MLXSW_SP_RIF_COUNTER_EXTRACT
  313
  314	return 0;
  315}
  316
  317static int mlxsw_sp_rif_counter_clear(struct mlxsw_sp *mlxsw_sp,
  318				      unsigned int counter_index)
  319{
  320	char ricnt_pl[MLXSW_REG_RICNT_LEN];
  321
  322	mlxsw_reg_ricnt_pack(ricnt_pl, counter_index,
  323			     MLXSW_REG_RICNT_OPCODE_CLEAR);
  324	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl);
  325}
  326
  327int mlxsw_sp_rif_counter_alloc(struct mlxsw_sp_rif *rif,
  328			       enum mlxsw_sp_rif_counter_dir dir)
  329{
  330	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
  331	unsigned int *p_counter_index;
  332	int err;
  333
  334	if (mlxsw_sp_rif_counter_valid_get(rif, dir))
  335		return 0;
  336
  337	p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
  338	if (!p_counter_index)
  339		return -EINVAL;
  340
  341	err = mlxsw_sp_counter_alloc(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
  342				     p_counter_index);
  343	if (err)
  344		return err;
  345
  346	err = mlxsw_sp_rif_counter_clear(mlxsw_sp, *p_counter_index);
  347	if (err)
  348		goto err_counter_clear;
  349
  350	err = mlxsw_sp_rif_counter_edit(mlxsw_sp, rif->rif_index,
  351					*p_counter_index, true, dir);
  352	if (err)
  353		goto err_counter_edit;
  354	mlxsw_sp_rif_counter_valid_set(rif, dir, true);
  355	return 0;
  356
  357err_counter_edit:
  358err_counter_clear:
  359	mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
  360			      *p_counter_index);
  361	return err;
  362}
  363
  364void mlxsw_sp_rif_counter_free(struct mlxsw_sp_rif *rif,
  365			       enum mlxsw_sp_rif_counter_dir dir)
  366{
  367	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
  368	unsigned int *p_counter_index;
  369
  370	if (!mlxsw_sp_rif_counter_valid_get(rif, dir))
  371		return;
  372
  373	p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
  374	if (WARN_ON(!p_counter_index))
  375		return;
  376	mlxsw_sp_rif_counter_edit(mlxsw_sp, rif->rif_index,
  377				  *p_counter_index, false, dir);
  378	mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
  379			      *p_counter_index);
  380	mlxsw_sp_rif_counter_valid_set(rif, dir, false);
  381}
  382
  383static void mlxsw_sp_rif_counters_alloc(struct mlxsw_sp_rif *rif)
  384{
  385	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
  386	struct devlink *devlink;
  387
  388	devlink = priv_to_devlink(mlxsw_sp->core);
  389	if (!devlink_dpipe_table_counter_enabled(devlink,
  390						 MLXSW_SP_DPIPE_TABLE_NAME_ERIF))
  391		return;
  392	mlxsw_sp_rif_counter_alloc(rif, MLXSW_SP_RIF_COUNTER_EGRESS);
  393}
  394
  395static void mlxsw_sp_rif_counters_free(struct mlxsw_sp_rif *rif)
  396{
  397	mlxsw_sp_rif_counter_free(rif, MLXSW_SP_RIF_COUNTER_EGRESS);
  398}
  399
  400#define MLXSW_SP_PREFIX_COUNT (sizeof(struct in6_addr) * BITS_PER_BYTE + 1)
  401
  402struct mlxsw_sp_prefix_usage {
  403	DECLARE_BITMAP(b, MLXSW_SP_PREFIX_COUNT);
  404};
  405
  406#define mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) \
  407	for_each_set_bit(prefix, (prefix_usage)->b, MLXSW_SP_PREFIX_COUNT)
  408
  409static bool
  410mlxsw_sp_prefix_usage_eq(struct mlxsw_sp_prefix_usage *prefix_usage1,
  411			 struct mlxsw_sp_prefix_usage *prefix_usage2)
  412{
  413	return !memcmp(prefix_usage1, prefix_usage2, sizeof(*prefix_usage1));
  414}
  415
  416static void
  417mlxsw_sp_prefix_usage_cpy(struct mlxsw_sp_prefix_usage *prefix_usage1,
  418			  struct mlxsw_sp_prefix_usage *prefix_usage2)
  419{
  420	memcpy(prefix_usage1, prefix_usage2, sizeof(*prefix_usage1));
  421}
  422
  423static void
  424mlxsw_sp_prefix_usage_set(struct mlxsw_sp_prefix_usage *prefix_usage,
  425			  unsigned char prefix_len)
  426{
  427	set_bit(prefix_len, prefix_usage->b);
  428}
  429
  430static void
  431mlxsw_sp_prefix_usage_clear(struct mlxsw_sp_prefix_usage *prefix_usage,
  432			    unsigned char prefix_len)
  433{
  434	clear_bit(prefix_len, prefix_usage->b);
  435}
  436
  437struct mlxsw_sp_fib_key {
  438	unsigned char addr[sizeof(struct in6_addr)];
  439	unsigned char prefix_len;
  440};
  441
  442enum mlxsw_sp_fib_entry_type {
  443	MLXSW_SP_FIB_ENTRY_TYPE_REMOTE,
  444	MLXSW_SP_FIB_ENTRY_TYPE_LOCAL,
  445	MLXSW_SP_FIB_ENTRY_TYPE_TRAP,
  446	MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE,
  447	MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE,
  448
  449	/* This is a special case of local delivery, where a packet should be
  450	 * decapsulated on reception. Note that there is no corresponding ENCAP,
  451	 * because that's a type of next hop, not of FIB entry. (There can be
  452	 * several next hops in a REMOTE entry, and some of them may be
  453	 * encapsulating entries.)
  454	 */
  455	MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP,
  456	MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP,
  457};
  458
  459struct mlxsw_sp_nexthop_group_info;
  460struct mlxsw_sp_nexthop_group;
  461struct mlxsw_sp_fib_entry;
  462
  463struct mlxsw_sp_fib_node {
  464	struct mlxsw_sp_fib_entry *fib_entry;
  465	struct list_head list;
  466	struct rhash_head ht_node;
  467	struct mlxsw_sp_fib *fib;
  468	struct mlxsw_sp_fib_key key;
  469};
  470
  471struct mlxsw_sp_fib_entry_decap {
  472	struct mlxsw_sp_ipip_entry *ipip_entry;
  473	u32 tunnel_index;
  474};
  475
  476struct mlxsw_sp_fib_entry {
  477	struct mlxsw_sp_fib_node *fib_node;
  478	enum mlxsw_sp_fib_entry_type type;
  479	struct list_head nexthop_group_node;
  480	struct mlxsw_sp_nexthop_group *nh_group;
  481	struct mlxsw_sp_fib_entry_decap decap; /* Valid for decap entries. */
  482};
  483
  484struct mlxsw_sp_fib4_entry {
  485	struct mlxsw_sp_fib_entry common;
  486	struct fib_info *fi;
  487	u32 tb_id;
  488	dscp_t dscp;
  489	u8 type;
  490};
  491
  492struct mlxsw_sp_fib6_entry {
  493	struct mlxsw_sp_fib_entry common;
  494	struct list_head rt6_list;
  495	unsigned int nrt6;
  496};
  497
  498struct mlxsw_sp_rt6 {
  499	struct list_head list;
  500	struct fib6_info *rt;
  501};
  502
  503struct mlxsw_sp_lpm_tree {
  504	u8 id; /* tree ID */
  505	refcount_t ref_count;
  506	enum mlxsw_sp_l3proto proto;
  507	unsigned long prefix_ref_count[MLXSW_SP_PREFIX_COUNT];
  508	struct mlxsw_sp_prefix_usage prefix_usage;
  509};
  510
  511struct mlxsw_sp_fib {
  512	struct rhashtable ht;
  513	struct list_head node_list;
  514	struct mlxsw_sp_vr *vr;
  515	struct mlxsw_sp_lpm_tree *lpm_tree;
  516	enum mlxsw_sp_l3proto proto;
  517};
  518
  519struct mlxsw_sp_vr {
  520	u16 id; /* virtual router ID */
  521	u32 tb_id; /* kernel fib table id */
  522	unsigned int rif_count;
  523	struct mlxsw_sp_fib *fib4;
  524	struct mlxsw_sp_fib *fib6;
  525	struct mlxsw_sp_mr_table *mr_table[MLXSW_SP_L3_PROTO_MAX];
  526	struct mlxsw_sp_rif *ul_rif;
  527	refcount_t ul_rif_refcnt;
  528};
  529
  530static const struct rhashtable_params mlxsw_sp_fib_ht_params;
  531
  532static struct mlxsw_sp_fib *mlxsw_sp_fib_create(struct mlxsw_sp *mlxsw_sp,
  533						struct mlxsw_sp_vr *vr,
  534						enum mlxsw_sp_l3proto proto)
  535{
  536	struct mlxsw_sp_lpm_tree *lpm_tree;
  537	struct mlxsw_sp_fib *fib;
  538	int err;
  539
  540	lpm_tree = mlxsw_sp->router->lpm.proto_trees[proto];
  541	fib = kzalloc(sizeof(*fib), GFP_KERNEL);
  542	if (!fib)
  543		return ERR_PTR(-ENOMEM);
  544	err = rhashtable_init(&fib->ht, &mlxsw_sp_fib_ht_params);
  545	if (err)
  546		goto err_rhashtable_init;
  547	INIT_LIST_HEAD(&fib->node_list);
  548	fib->proto = proto;
  549	fib->vr = vr;
  550	fib->lpm_tree = lpm_tree;
  551	mlxsw_sp_lpm_tree_hold(lpm_tree);
  552	err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, lpm_tree->id);
  553	if (err)
  554		goto err_lpm_tree_bind;
  555	return fib;
  556
  557err_lpm_tree_bind:
  558	mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
  559err_rhashtable_init:
  560	kfree(fib);
  561	return ERR_PTR(err);
  562}
  563
  564static void mlxsw_sp_fib_destroy(struct mlxsw_sp *mlxsw_sp,
  565				 struct mlxsw_sp_fib *fib)
  566{
  567	mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp, fib);
  568	mlxsw_sp_lpm_tree_put(mlxsw_sp, fib->lpm_tree);
  569	WARN_ON(!list_empty(&fib->node_list));
  570	rhashtable_destroy(&fib->ht);
  571	kfree(fib);
  572}
  573
  574static struct mlxsw_sp_lpm_tree *
  575mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp *mlxsw_sp)
  576{
  577	static struct mlxsw_sp_lpm_tree *lpm_tree;
  578	int i;
  579
  580	for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
  581		lpm_tree = &mlxsw_sp->router->lpm.trees[i];
  582		if (refcount_read(&lpm_tree->ref_count) == 0)
  583			return lpm_tree;
  584	}
  585	return NULL;
  586}
  587
  588static int mlxsw_sp_lpm_tree_alloc(struct mlxsw_sp *mlxsw_sp,
  589				   struct mlxsw_sp_lpm_tree *lpm_tree)
  590{
  591	char ralta_pl[MLXSW_REG_RALTA_LEN];
  592
  593	mlxsw_reg_ralta_pack(ralta_pl, true,
  594			     (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto,
  595			     lpm_tree->id);
  596	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
  597}
  598
  599static void mlxsw_sp_lpm_tree_free(struct mlxsw_sp *mlxsw_sp,
  600				   struct mlxsw_sp_lpm_tree *lpm_tree)
  601{
  602	char ralta_pl[MLXSW_REG_RALTA_LEN];
  603
  604	mlxsw_reg_ralta_pack(ralta_pl, false,
  605			     (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto,
  606			     lpm_tree->id);
  607	mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
  608}
  609
  610static int
  611mlxsw_sp_lpm_tree_left_struct_set(struct mlxsw_sp *mlxsw_sp,
  612				  struct mlxsw_sp_prefix_usage *prefix_usage,
  613				  struct mlxsw_sp_lpm_tree *lpm_tree)
  614{
  615	char ralst_pl[MLXSW_REG_RALST_LEN];
  616	u8 root_bin = 0;
  617	u8 prefix;
  618	u8 last_prefix = MLXSW_REG_RALST_BIN_NO_CHILD;
  619
  620	mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage)
  621		root_bin = prefix;
  622
  623	mlxsw_reg_ralst_pack(ralst_pl, root_bin, lpm_tree->id);
  624	mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) {
  625		if (prefix == 0)
  626			continue;
  627		mlxsw_reg_ralst_bin_pack(ralst_pl, prefix, last_prefix,
  628					 MLXSW_REG_RALST_BIN_NO_CHILD);
  629		last_prefix = prefix;
  630	}
  631	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), ralst_pl);
  632}
  633
  634static struct mlxsw_sp_lpm_tree *
  635mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp,
  636			 struct mlxsw_sp_prefix_usage *prefix_usage,
  637			 enum mlxsw_sp_l3proto proto)
  638{
  639	struct mlxsw_sp_lpm_tree *lpm_tree;
  640	int err;
  641
  642	lpm_tree = mlxsw_sp_lpm_tree_find_unused(mlxsw_sp);
  643	if (!lpm_tree)
  644		return ERR_PTR(-EBUSY);
  645	lpm_tree->proto = proto;
  646	err = mlxsw_sp_lpm_tree_alloc(mlxsw_sp, lpm_tree);
  647	if (err)
  648		return ERR_PTR(err);
  649
  650	err = mlxsw_sp_lpm_tree_left_struct_set(mlxsw_sp, prefix_usage,
  651						lpm_tree);
  652	if (err)
  653		goto err_left_struct_set;
  654	memcpy(&lpm_tree->prefix_usage, prefix_usage,
  655	       sizeof(lpm_tree->prefix_usage));
  656	memset(&lpm_tree->prefix_ref_count, 0,
  657	       sizeof(lpm_tree->prefix_ref_count));
  658	refcount_set(&lpm_tree->ref_count, 1);
  659	return lpm_tree;
  660
  661err_left_struct_set:
  662	mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree);
  663	return ERR_PTR(err);
  664}
  665
  666static void mlxsw_sp_lpm_tree_destroy(struct mlxsw_sp *mlxsw_sp,
  667				      struct mlxsw_sp_lpm_tree *lpm_tree)
  668{
  669	mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree);
  670}
  671
  672static struct mlxsw_sp_lpm_tree *
  673mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp,
  674		      struct mlxsw_sp_prefix_usage *prefix_usage,
  675		      enum mlxsw_sp_l3proto proto)
  676{
  677	struct mlxsw_sp_lpm_tree *lpm_tree;
  678	int i;
  679
  680	for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
  681		lpm_tree = &mlxsw_sp->router->lpm.trees[i];
  682		if (refcount_read(&lpm_tree->ref_count) &&
  683		    lpm_tree->proto == proto &&
  684		    mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage,
  685					     prefix_usage)) {
  686			mlxsw_sp_lpm_tree_hold(lpm_tree);
  687			return lpm_tree;
  688		}
  689	}
  690	return mlxsw_sp_lpm_tree_create(mlxsw_sp, prefix_usage, proto);
  691}
  692
  693static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree)
  694{
  695	refcount_inc(&lpm_tree->ref_count);
  696}
  697
  698static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
  699				  struct mlxsw_sp_lpm_tree *lpm_tree)
  700{
  701	if (!refcount_dec_and_test(&lpm_tree->ref_count))
  702		return;
  703	mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree);
  704}
  705
  706#define MLXSW_SP_LPM_TREE_MIN 1 /* tree 0 is reserved */
  707
  708static int mlxsw_sp_lpm_init(struct mlxsw_sp *mlxsw_sp)
  709{
  710	struct mlxsw_sp_prefix_usage req_prefix_usage = {{ 0 } };
  711	struct mlxsw_sp_lpm_tree *lpm_tree;
  712	u64 max_trees;
  713	int err, i;
  714
  715	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LPM_TREES))
  716		return -EIO;
  717
  718	max_trees = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LPM_TREES);
  719	mlxsw_sp->router->lpm.tree_count = max_trees - MLXSW_SP_LPM_TREE_MIN;
  720	mlxsw_sp->router->lpm.trees = kcalloc(mlxsw_sp->router->lpm.tree_count,
  721					     sizeof(struct mlxsw_sp_lpm_tree),
  722					     GFP_KERNEL);
  723	if (!mlxsw_sp->router->lpm.trees)
  724		return -ENOMEM;
  725
  726	for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
  727		lpm_tree = &mlxsw_sp->router->lpm.trees[i];
  728		lpm_tree->id = i + MLXSW_SP_LPM_TREE_MIN;
  729	}
  730
  731	lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
  732					 MLXSW_SP_L3_PROTO_IPV4);
  733	if (IS_ERR(lpm_tree)) {
  734		err = PTR_ERR(lpm_tree);
  735		goto err_ipv4_tree_get;
  736	}
  737	mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV4] = lpm_tree;
  738
  739	lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
  740					 MLXSW_SP_L3_PROTO_IPV6);
  741	if (IS_ERR(lpm_tree)) {
  742		err = PTR_ERR(lpm_tree);
  743		goto err_ipv6_tree_get;
  744	}
  745	mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV6] = lpm_tree;
  746
  747	return 0;
  748
  749err_ipv6_tree_get:
  750	lpm_tree = mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV4];
  751	mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
  752err_ipv4_tree_get:
  753	kfree(mlxsw_sp->router->lpm.trees);
  754	return err;
  755}
  756
  757static void mlxsw_sp_lpm_fini(struct mlxsw_sp *mlxsw_sp)
  758{
  759	struct mlxsw_sp_lpm_tree *lpm_tree;
  760
  761	lpm_tree = mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV6];
  762	mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
  763
  764	lpm_tree = mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV4];
  765	mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
  766
  767	kfree(mlxsw_sp->router->lpm.trees);
  768}
  769
  770static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr)
  771{
  772	return !!vr->fib4 || !!vr->fib6 ||
  773	       !!vr->mr_table[MLXSW_SP_L3_PROTO_IPV4] ||
  774	       !!vr->mr_table[MLXSW_SP_L3_PROTO_IPV6];
  775}
  776
  777static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp)
  778{
  779	int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
  780	struct mlxsw_sp_vr *vr;
  781	int i;
  782
  783	for (i = 0; i < max_vrs; i++) {
  784		vr = &mlxsw_sp->router->vrs[i];
  785		if (!mlxsw_sp_vr_is_used(vr))
  786			return vr;
  787	}
  788	return NULL;
  789}
  790
  791static int mlxsw_sp_vr_lpm_tree_bind(struct mlxsw_sp *mlxsw_sp,
  792				     const struct mlxsw_sp_fib *fib, u8 tree_id)
  793{
  794	char raltb_pl[MLXSW_REG_RALTB_LEN];
  795
  796	mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id,
  797			     (enum mlxsw_reg_ralxx_protocol) fib->proto,
  798			     tree_id);
  799	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl);
  800}
  801
  802static int mlxsw_sp_vr_lpm_tree_unbind(struct mlxsw_sp *mlxsw_sp,
  803				       const struct mlxsw_sp_fib *fib)
  804{
  805	char raltb_pl[MLXSW_REG_RALTB_LEN];
  806
  807	/* Bind to tree 0 which is default */
  808	mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id,
  809			     (enum mlxsw_reg_ralxx_protocol) fib->proto, 0);
  810	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl);
  811}
  812
  813static u32 mlxsw_sp_fix_tb_id(u32 tb_id)
  814{
  815	/* For our purpose, squash main, default and local tables into one */
  816	if (tb_id == RT_TABLE_LOCAL || tb_id == RT_TABLE_DEFAULT)
  817		tb_id = RT_TABLE_MAIN;
  818	return tb_id;
  819}
  820
  821static struct mlxsw_sp_vr *mlxsw_sp_vr_find(struct mlxsw_sp *mlxsw_sp,
  822					    u32 tb_id)
  823{
  824	int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
  825	struct mlxsw_sp_vr *vr;
  826	int i;
  827
  828	tb_id = mlxsw_sp_fix_tb_id(tb_id);
  829
  830	for (i = 0; i < max_vrs; i++) {
  831		vr = &mlxsw_sp->router->vrs[i];
  832		if (mlxsw_sp_vr_is_used(vr) && vr->tb_id == tb_id)
  833			return vr;
  834	}
  835	return NULL;
  836}
  837
  838int mlxsw_sp_router_tb_id_vr_id(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
  839				u16 *vr_id)
  840{
  841	struct mlxsw_sp_vr *vr;
  842	int err = 0;
  843
  844	mutex_lock(&mlxsw_sp->router->lock);
  845	vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id);
  846	if (!vr) {
  847		err = -ESRCH;
  848		goto out;
  849	}
  850	*vr_id = vr->id;
  851out:
  852	mutex_unlock(&mlxsw_sp->router->lock);
  853	return err;
  854}
  855
  856static struct mlxsw_sp_fib *mlxsw_sp_vr_fib(const struct mlxsw_sp_vr *vr,
  857					    enum mlxsw_sp_l3proto proto)
  858{
  859	switch (proto) {
  860	case MLXSW_SP_L3_PROTO_IPV4:
  861		return vr->fib4;
  862	case MLXSW_SP_L3_PROTO_IPV6:
  863		return vr->fib6;
  864	}
  865	return NULL;
  866}
  867
  868static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp,
  869					      u32 tb_id,
  870					      struct netlink_ext_ack *extack)
  871{
  872	struct mlxsw_sp_mr_table *mr4_table, *mr6_table;
  873	struct mlxsw_sp_fib *fib4;
  874	struct mlxsw_sp_fib *fib6;
  875	struct mlxsw_sp_vr *vr;
  876	int err;
  877
  878	vr = mlxsw_sp_vr_find_unused(mlxsw_sp);
  879	if (!vr) {
  880		NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported virtual routers");
  881		return ERR_PTR(-EBUSY);
  882	}
  883	fib4 = mlxsw_sp_fib_create(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4);
  884	if (IS_ERR(fib4))
  885		return ERR_CAST(fib4);
  886	fib6 = mlxsw_sp_fib_create(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV6);
  887	if (IS_ERR(fib6)) {
  888		err = PTR_ERR(fib6);
  889		goto err_fib6_create;
  890	}
  891	mr4_table = mlxsw_sp_mr_table_create(mlxsw_sp, vr->id,
  892					     MLXSW_SP_L3_PROTO_IPV4);
  893	if (IS_ERR(mr4_table)) {
  894		err = PTR_ERR(mr4_table);
  895		goto err_mr4_table_create;
  896	}
  897	mr6_table = mlxsw_sp_mr_table_create(mlxsw_sp, vr->id,
  898					     MLXSW_SP_L3_PROTO_IPV6);
  899	if (IS_ERR(mr6_table)) {
  900		err = PTR_ERR(mr6_table);
  901		goto err_mr6_table_create;
  902	}
  903
  904	vr->fib4 = fib4;
  905	vr->fib6 = fib6;
  906	vr->mr_table[MLXSW_SP_L3_PROTO_IPV4] = mr4_table;
  907	vr->mr_table[MLXSW_SP_L3_PROTO_IPV6] = mr6_table;
  908	vr->tb_id = tb_id;
  909	return vr;
  910
  911err_mr6_table_create:
  912	mlxsw_sp_mr_table_destroy(mr4_table);
  913err_mr4_table_create:
  914	mlxsw_sp_fib_destroy(mlxsw_sp, fib6);
  915err_fib6_create:
  916	mlxsw_sp_fib_destroy(mlxsw_sp, fib4);
  917	return ERR_PTR(err);
  918}
  919
  920static void mlxsw_sp_vr_destroy(struct mlxsw_sp *mlxsw_sp,
  921				struct mlxsw_sp_vr *vr)
  922{
  923	mlxsw_sp_mr_table_destroy(vr->mr_table[MLXSW_SP_L3_PROTO_IPV6]);
  924	vr->mr_table[MLXSW_SP_L3_PROTO_IPV6] = NULL;
  925	mlxsw_sp_mr_table_destroy(vr->mr_table[MLXSW_SP_L3_PROTO_IPV4]);
  926	vr->mr_table[MLXSW_SP_L3_PROTO_IPV4] = NULL;
  927	mlxsw_sp_fib_destroy(mlxsw_sp, vr->fib6);
  928	vr->fib6 = NULL;
  929	mlxsw_sp_fib_destroy(mlxsw_sp, vr->fib4);
  930	vr->fib4 = NULL;
  931}
  932
  933static struct mlxsw_sp_vr *mlxsw_sp_vr_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
  934					   struct netlink_ext_ack *extack)
  935{
  936	struct mlxsw_sp_vr *vr;
  937
  938	tb_id = mlxsw_sp_fix_tb_id(tb_id);
  939	vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id);
  940	if (!vr)
  941		vr = mlxsw_sp_vr_create(mlxsw_sp, tb_id, extack);
  942	return vr;
  943}
  944
  945static void mlxsw_sp_vr_put(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr)
  946{
  947	if (!vr->rif_count && list_empty(&vr->fib4->node_list) &&
  948	    list_empty(&vr->fib6->node_list) &&
  949	    mlxsw_sp_mr_table_empty(vr->mr_table[MLXSW_SP_L3_PROTO_IPV4]) &&
  950	    mlxsw_sp_mr_table_empty(vr->mr_table[MLXSW_SP_L3_PROTO_IPV6]))
  951		mlxsw_sp_vr_destroy(mlxsw_sp, vr);
  952}
  953
  954static bool
  955mlxsw_sp_vr_lpm_tree_should_replace(struct mlxsw_sp_vr *vr,
  956				    enum mlxsw_sp_l3proto proto, u8 tree_id)
  957{
  958	struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto);
  959
  960	if (!mlxsw_sp_vr_is_used(vr))
  961		return false;
  962	if (fib->lpm_tree->id == tree_id)
  963		return true;
  964	return false;
  965}
  966
  967static int mlxsw_sp_vr_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
  968					struct mlxsw_sp_fib *fib,
  969					struct mlxsw_sp_lpm_tree *new_tree)
  970{
  971	struct mlxsw_sp_lpm_tree *old_tree = fib->lpm_tree;
  972	int err;
  973
  974	fib->lpm_tree = new_tree;
  975	mlxsw_sp_lpm_tree_hold(new_tree);
  976	err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id);
  977	if (err)
  978		goto err_tree_bind;
  979	mlxsw_sp_lpm_tree_put(mlxsw_sp, old_tree);
  980	return 0;
  981
  982err_tree_bind:
  983	mlxsw_sp_lpm_tree_put(mlxsw_sp, new_tree);
  984	fib->lpm_tree = old_tree;
  985	return err;
  986}
  987
  988static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
  989					 struct mlxsw_sp_fib *fib,
  990					 struct mlxsw_sp_lpm_tree *new_tree)
  991{
  992	int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
  993	enum mlxsw_sp_l3proto proto = fib->proto;
  994	struct mlxsw_sp_lpm_tree *old_tree;
  995	u8 old_id, new_id = new_tree->id;
  996	struct mlxsw_sp_vr *vr;
  997	int i, err;
  998
  999	old_tree = mlxsw_sp->router->lpm.proto_trees[proto];
 1000	old_id = old_tree->id;
 1001
 1002	for (i = 0; i < max_vrs; i++) {
 1003		vr = &mlxsw_sp->router->vrs[i];
 1004		if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, old_id))
 1005			continue;
 1006		err = mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp,
 1007						   mlxsw_sp_vr_fib(vr, proto),
 1008						   new_tree);
 1009		if (err)
 1010			goto err_tree_replace;
 1011	}
 1012
 1013	memcpy(new_tree->prefix_ref_count, old_tree->prefix_ref_count,
 1014	       sizeof(new_tree->prefix_ref_count));
 1015	mlxsw_sp->router->lpm.proto_trees[proto] = new_tree;
 1016	mlxsw_sp_lpm_tree_put(mlxsw_sp, old_tree);
 1017
 1018	return 0;
 1019
 1020err_tree_replace:
 1021	for (i--; i >= 0; i--) {
 1022		if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, new_id))
 1023			continue;
 1024		mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp,
 1025					     mlxsw_sp_vr_fib(vr, proto),
 1026					     old_tree);
 1027	}
 1028	return err;
 1029}
 1030
 1031static int mlxsw_sp_vrs_init(struct mlxsw_sp *mlxsw_sp)
 1032{
 1033	struct mlxsw_sp_vr *vr;
 1034	u64 max_vrs;
 1035	int i;
 1036
 1037	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_VRS))
 1038		return -EIO;
 1039
 1040	max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
 1041	mlxsw_sp->router->vrs = kcalloc(max_vrs, sizeof(struct mlxsw_sp_vr),
 1042					GFP_KERNEL);
 1043	if (!mlxsw_sp->router->vrs)
 1044		return -ENOMEM;
 1045
 1046	for (i = 0; i < max_vrs; i++) {
 1047		vr = &mlxsw_sp->router->vrs[i];
 1048		vr->id = i;
 1049	}
 1050
 1051	return 0;
 1052}
 1053
 1054static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp);
 1055
 1056static void mlxsw_sp_vrs_fini(struct mlxsw_sp *mlxsw_sp)
 1057{
 1058	/* At this stage we're guaranteed not to have new incoming
 1059	 * FIB notifications and the work queue is free from FIBs
 1060	 * sitting on top of mlxsw netdevs. However, we can still
 1061	 * have other FIBs queued. Flush the queue before flushing
 1062	 * the device's tables. No need for locks, as we're the only
 1063	 * writer.
 1064	 */
 1065	mlxsw_core_flush_owq();
 1066	mlxsw_sp_router_fib_flush(mlxsw_sp);
 1067	kfree(mlxsw_sp->router->vrs);
 1068}
 1069
 1070u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev)
 1071{
 1072	struct net_device *d;
 1073	u32 tb_id;
 1074
 1075	rcu_read_lock();
 1076	d = mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
 1077	if (d)
 1078		tb_id = l3mdev_fib_table(d) ? : RT_TABLE_MAIN;
 1079	else
 1080		tb_id = RT_TABLE_MAIN;
 1081	rcu_read_unlock();
 1082
 1083	return tb_id;
 1084}
 1085
 1086static void
 1087mlxsw_sp_crif_init(struct mlxsw_sp_crif *crif, struct net_device *dev)
 1088{
 1089	crif->key.dev = dev;
 1090	INIT_LIST_HEAD(&crif->nexthop_list);
 1091}
 1092
 1093static struct mlxsw_sp_crif *
 1094mlxsw_sp_crif_alloc(struct net_device *dev)
 1095{
 1096	struct mlxsw_sp_crif *crif;
 1097
 1098	crif = kzalloc(sizeof(*crif), GFP_KERNEL);
 1099	if (!crif)
 1100		return NULL;
 1101
 1102	mlxsw_sp_crif_init(crif, dev);
 1103	return crif;
 1104}
 1105
 1106static void mlxsw_sp_crif_free(struct mlxsw_sp_crif *crif)
 1107{
 1108	if (WARN_ON(crif->rif))
 1109		return;
 1110
 1111	WARN_ON(!list_empty(&crif->nexthop_list));
 1112	kfree(crif);
 1113}
 1114
 1115static int mlxsw_sp_crif_insert(struct mlxsw_sp_router *router,
 1116				struct mlxsw_sp_crif *crif)
 1117{
 1118	return rhashtable_insert_fast(&router->crif_ht, &crif->ht_node,
 1119				      mlxsw_sp_crif_ht_params);
 1120}
 1121
 1122static void mlxsw_sp_crif_remove(struct mlxsw_sp_router *router,
 1123				 struct mlxsw_sp_crif *crif)
 1124{
 1125	rhashtable_remove_fast(&router->crif_ht, &crif->ht_node,
 1126			       mlxsw_sp_crif_ht_params);
 1127}
 1128
 1129static struct mlxsw_sp_crif *
 1130mlxsw_sp_crif_lookup(struct mlxsw_sp_router *router,
 1131		     const struct net_device *dev)
 1132{
 1133	struct mlxsw_sp_crif_key key = {
 1134		.dev = (struct net_device *)dev,
 1135	};
 1136
 1137	return rhashtable_lookup_fast(&router->crif_ht, &key,
 1138				      mlxsw_sp_crif_ht_params);
 1139}
 1140
 1141static struct mlxsw_sp_rif *
 1142mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
 1143		    const struct mlxsw_sp_rif_params *params,
 1144		    struct netlink_ext_ack *extack);
 1145
 1146static struct mlxsw_sp_rif_ipip_lb *
 1147mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp *mlxsw_sp,
 1148				enum mlxsw_sp_ipip_type ipipt,
 1149				struct net_device *ol_dev,
 1150				struct netlink_ext_ack *extack)
 1151{
 1152	struct mlxsw_sp_rif_params_ipip_lb lb_params;
 1153	const struct mlxsw_sp_ipip_ops *ipip_ops;
 1154	struct mlxsw_sp_rif *rif;
 1155
 1156	ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipipt];
 1157	lb_params = (struct mlxsw_sp_rif_params_ipip_lb) {
 1158		.common.dev = ol_dev,
 1159		.common.lag = false,
 1160		.common.double_entry = ipip_ops->double_rif_entry,
 1161		.lb_config = ipip_ops->ol_loopback_config(mlxsw_sp, ol_dev),
 1162	};
 1163
 1164	rif = mlxsw_sp_rif_create(mlxsw_sp, &lb_params.common, extack);
 1165	if (IS_ERR(rif))
 1166		return ERR_CAST(rif);
 1167	return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common);
 1168}
 1169
 1170static struct mlxsw_sp_ipip_entry *
 1171mlxsw_sp_ipip_entry_alloc(struct mlxsw_sp *mlxsw_sp,
 1172			  enum mlxsw_sp_ipip_type ipipt,
 1173			  struct net_device *ol_dev)
 1174{
 1175	const struct mlxsw_sp_ipip_ops *ipip_ops;
 1176	struct mlxsw_sp_ipip_entry *ipip_entry;
 1177	struct mlxsw_sp_ipip_entry *ret = NULL;
 1178	int err;
 1179
 1180	ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipipt];
 1181	ipip_entry = kzalloc(sizeof(*ipip_entry), GFP_KERNEL);
 1182	if (!ipip_entry)
 1183		return ERR_PTR(-ENOMEM);
 1184
 1185	ipip_entry->ol_lb = mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp, ipipt,
 1186							    ol_dev, NULL);
 1187	if (IS_ERR(ipip_entry->ol_lb)) {
 1188		ret = ERR_CAST(ipip_entry->ol_lb);
 1189		goto err_ol_ipip_lb_create;
 1190	}
 1191
 1192	ipip_entry->ipipt = ipipt;
 1193	ipip_entry->ol_dev = ol_dev;
 1194	ipip_entry->parms = ipip_ops->parms_init(ol_dev);
 1195
 1196	err = ipip_ops->rem_ip_addr_set(mlxsw_sp, ipip_entry);
 1197	if (err) {
 1198		ret = ERR_PTR(err);
 1199		goto err_rem_ip_addr_set;
 1200	}
 1201
 1202	return ipip_entry;
 1203
 1204err_rem_ip_addr_set:
 1205	mlxsw_sp_rif_destroy(&ipip_entry->ol_lb->common);
 1206err_ol_ipip_lb_create:
 1207	kfree(ipip_entry);
 1208	return ret;
 1209}
 1210
 1211static void mlxsw_sp_ipip_entry_dealloc(struct mlxsw_sp *mlxsw_sp,
 1212					struct mlxsw_sp_ipip_entry *ipip_entry)
 1213{
 1214	const struct mlxsw_sp_ipip_ops *ipip_ops =
 1215		mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
 1216
 1217	ipip_ops->rem_ip_addr_unset(mlxsw_sp, ipip_entry);
 1218	mlxsw_sp_rif_destroy(&ipip_entry->ol_lb->common);
 1219	kfree(ipip_entry);
 1220}
 1221
 1222static bool
 1223mlxsw_sp_ipip_entry_saddr_matches(struct mlxsw_sp *mlxsw_sp,
 1224				  const enum mlxsw_sp_l3proto ul_proto,
 1225				  union mlxsw_sp_l3addr saddr,
 1226				  u32 ul_tb_id,
 1227				  struct mlxsw_sp_ipip_entry *ipip_entry)
 1228{
 1229	u32 tun_ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev);
 1230	enum mlxsw_sp_ipip_type ipipt = ipip_entry->ipipt;
 1231	union mlxsw_sp_l3addr tun_saddr;
 1232
 1233	if (mlxsw_sp->router->ipip_ops_arr[ipipt]->ul_proto != ul_proto)
 1234		return false;
 1235
 1236	tun_saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ipip_entry->ol_dev);
 1237	return tun_ul_tb_id == ul_tb_id &&
 1238	       mlxsw_sp_l3addr_eq(&tun_saddr, &saddr);
 1239}
 1240
 1241static int mlxsw_sp_ipip_decap_parsing_depth_inc(struct mlxsw_sp *mlxsw_sp,
 1242						 enum mlxsw_sp_ipip_type ipipt)
 1243{
 1244	const struct mlxsw_sp_ipip_ops *ipip_ops;
 1245
 1246	ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipipt];
 1247
 1248	/* Not all tunnels require to increase the default pasing depth
 1249	 * (96 bytes).
 1250	 */
 1251	if (ipip_ops->inc_parsing_depth)
 1252		return mlxsw_sp_parsing_depth_inc(mlxsw_sp);
 1253
 1254	return 0;
 1255}
 1256
 1257static void mlxsw_sp_ipip_decap_parsing_depth_dec(struct mlxsw_sp *mlxsw_sp,
 1258						  enum mlxsw_sp_ipip_type ipipt)
 1259{
 1260	const struct mlxsw_sp_ipip_ops *ipip_ops =
 1261		mlxsw_sp->router->ipip_ops_arr[ipipt];
 1262
 1263	if (ipip_ops->inc_parsing_depth)
 1264		mlxsw_sp_parsing_depth_dec(mlxsw_sp);
 1265}
 1266
 1267static int
 1268mlxsw_sp_fib_entry_decap_init(struct mlxsw_sp *mlxsw_sp,
 1269			      struct mlxsw_sp_fib_entry *fib_entry,
 1270			      struct mlxsw_sp_ipip_entry *ipip_entry)
 1271{
 1272	u32 tunnel_index;
 1273	int err;
 1274
 1275	err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
 1276				  1, &tunnel_index);
 1277	if (err)
 1278		return err;
 1279
 1280	err = mlxsw_sp_ipip_decap_parsing_depth_inc(mlxsw_sp,
 1281						    ipip_entry->ipipt);
 1282	if (err)
 1283		goto err_parsing_depth_inc;
 1284
 1285	ipip_entry->decap_fib_entry = fib_entry;
 1286	fib_entry->decap.ipip_entry = ipip_entry;
 1287	fib_entry->decap.tunnel_index = tunnel_index;
 1288
 1289	return 0;
 1290
 1291err_parsing_depth_inc:
 1292	mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
 1293			   fib_entry->decap.tunnel_index);
 1294	return err;
 1295}
 1296
 1297static void mlxsw_sp_fib_entry_decap_fini(struct mlxsw_sp *mlxsw_sp,
 1298					  struct mlxsw_sp_fib_entry *fib_entry)
 1299{
 1300	enum mlxsw_sp_ipip_type ipipt = fib_entry->decap.ipip_entry->ipipt;
 1301
 1302	/* Unlink this node from the IPIP entry that it's the decap entry of. */
 1303	fib_entry->decap.ipip_entry->decap_fib_entry = NULL;
 1304	fib_entry->decap.ipip_entry = NULL;
 1305	mlxsw_sp_ipip_decap_parsing_depth_dec(mlxsw_sp, ipipt);
 1306	mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
 1307			   1, fib_entry->decap.tunnel_index);
 1308}
 1309
 1310static struct mlxsw_sp_fib_node *
 1311mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr,
 1312			 size_t addr_len, unsigned char prefix_len);
 1313static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp,
 1314				     struct mlxsw_sp_fib_entry *fib_entry);
 1315
 1316static void
 1317mlxsw_sp_ipip_entry_demote_decap(struct mlxsw_sp *mlxsw_sp,
 1318				 struct mlxsw_sp_ipip_entry *ipip_entry)
 1319{
 1320	struct mlxsw_sp_fib_entry *fib_entry = ipip_entry->decap_fib_entry;
 1321
 1322	mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, fib_entry);
 1323	fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
 1324
 1325	mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
 1326}
 1327
 1328static void
 1329mlxsw_sp_ipip_entry_promote_decap(struct mlxsw_sp *mlxsw_sp,
 1330				  struct mlxsw_sp_ipip_entry *ipip_entry,
 1331				  struct mlxsw_sp_fib_entry *decap_fib_entry)
 1332{
 1333	if (mlxsw_sp_fib_entry_decap_init(mlxsw_sp, decap_fib_entry,
 1334					  ipip_entry))
 1335		return;
 1336	decap_fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP;
 1337
 1338	if (mlxsw_sp_fib_entry_update(mlxsw_sp, decap_fib_entry))
 1339		mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
 1340}
 1341
 1342static struct mlxsw_sp_fib_entry *
 1343mlxsw_sp_router_ip2me_fib_entry_find(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
 1344				     enum mlxsw_sp_l3proto proto,
 1345				     const union mlxsw_sp_l3addr *addr,
 1346				     enum mlxsw_sp_fib_entry_type type)
 1347{
 1348	struct mlxsw_sp_fib_node *fib_node;
 1349	unsigned char addr_prefix_len;
 1350	struct mlxsw_sp_fib *fib;
 1351	struct mlxsw_sp_vr *vr;
 1352	const void *addrp;
 1353	size_t addr_len;
 1354	u32 addr4;
 1355
 1356	vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id);
 1357	if (!vr)
 1358		return NULL;
 1359	fib = mlxsw_sp_vr_fib(vr, proto);
 1360
 1361	switch (proto) {
 1362	case MLXSW_SP_L3_PROTO_IPV4:
 1363		addr4 = be32_to_cpu(addr->addr4);
 1364		addrp = &addr4;
 1365		addr_len = 4;
 1366		addr_prefix_len = 32;
 1367		break;
 1368	case MLXSW_SP_L3_PROTO_IPV6:
 1369		addrp = &addr->addr6;
 1370		addr_len = 16;
 1371		addr_prefix_len = 128;
 1372		break;
 1373	default:
 1374		WARN_ON(1);
 1375		return NULL;
 1376	}
 1377
 1378	fib_node = mlxsw_sp_fib_node_lookup(fib, addrp, addr_len,
 1379					    addr_prefix_len);
 1380	if (!fib_node || fib_node->fib_entry->type != type)
 1381		return NULL;
 1382
 1383	return fib_node->fib_entry;
 1384}
 1385
 1386/* Given an IPIP entry, find the corresponding decap route. */
 1387static struct mlxsw_sp_fib_entry *
 1388mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp *mlxsw_sp,
 1389			       struct mlxsw_sp_ipip_entry *ipip_entry)
 1390{
 1391	static struct mlxsw_sp_fib_node *fib_node;
 1392	const struct mlxsw_sp_ipip_ops *ipip_ops;
 1393	unsigned char saddr_prefix_len;
 1394	union mlxsw_sp_l3addr saddr;
 1395	struct mlxsw_sp_fib *ul_fib;
 1396	struct mlxsw_sp_vr *ul_vr;
 1397	const void *saddrp;
 1398	size_t saddr_len;
 1399	u32 ul_tb_id;
 1400	u32 saddr4;
 1401
 1402	ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
 1403
 1404	ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev);
 1405	ul_vr = mlxsw_sp_vr_find(mlxsw_sp, ul_tb_id);
 1406	if (!ul_vr)
 1407		return NULL;
 1408
 1409	ul_fib = mlxsw_sp_vr_fib(ul_vr, ipip_ops->ul_proto);
 1410	saddr = mlxsw_sp_ipip_netdev_saddr(ipip_ops->ul_proto,
 1411					   ipip_entry->ol_dev);
 1412
 1413	switch (ipip_ops->ul_proto) {
 1414	case MLXSW_SP_L3_PROTO_IPV4:
 1415		saddr4 = be32_to_cpu(saddr.addr4);
 1416		saddrp = &saddr4;
 1417		saddr_len = 4;
 1418		saddr_prefix_len = 32;
 1419		break;
 1420	case MLXSW_SP_L3_PROTO_IPV6:
 1421		saddrp = &saddr.addr6;
 1422		saddr_len = 16;
 1423		saddr_prefix_len = 128;
 1424		break;
 1425	default:
 1426		WARN_ON(1);
 1427		return NULL;
 1428	}
 1429
 1430	fib_node = mlxsw_sp_fib_node_lookup(ul_fib, saddrp, saddr_len,
 1431					    saddr_prefix_len);
 1432	if (!fib_node ||
 1433	    fib_node->fib_entry->type != MLXSW_SP_FIB_ENTRY_TYPE_TRAP)
 1434		return NULL;
 1435
 1436	return fib_node->fib_entry;
 1437}
 1438
 1439static struct mlxsw_sp_ipip_entry *
 1440mlxsw_sp_ipip_entry_create(struct mlxsw_sp *mlxsw_sp,
 1441			   enum mlxsw_sp_ipip_type ipipt,
 1442			   struct net_device *ol_dev)
 1443{
 1444	struct mlxsw_sp_ipip_entry *ipip_entry;
 1445
 1446	ipip_entry = mlxsw_sp_ipip_entry_alloc(mlxsw_sp, ipipt, ol_dev);
 1447	if (IS_ERR(ipip_entry))
 1448		return ipip_entry;
 1449
 1450	list_add_tail(&ipip_entry->ipip_list_node,
 1451		      &mlxsw_sp->router->ipip_list);
 1452
 1453	return ipip_entry;
 1454}
 1455
 1456static void
 1457mlxsw_sp_ipip_entry_destroy(struct mlxsw_sp *mlxsw_sp,
 1458			    struct mlxsw_sp_ipip_entry *ipip_entry)
 1459{
 1460	list_del(&ipip_entry->ipip_list_node);
 1461	mlxsw_sp_ipip_entry_dealloc(mlxsw_sp, ipip_entry);
 1462}
 1463
 1464static bool
 1465mlxsw_sp_ipip_entry_matches_decap(struct mlxsw_sp *mlxsw_sp,
 1466				  const struct net_device *ul_dev,
 1467				  enum mlxsw_sp_l3proto ul_proto,
 1468				  union mlxsw_sp_l3addr ul_dip,
 1469				  struct mlxsw_sp_ipip_entry *ipip_entry)
 1470{
 1471	u32 ul_tb_id = l3mdev_fib_table(ul_dev) ? : RT_TABLE_MAIN;
 1472	enum mlxsw_sp_ipip_type ipipt = ipip_entry->ipipt;
 1473
 1474	if (mlxsw_sp->router->ipip_ops_arr[ipipt]->ul_proto != ul_proto)
 1475		return false;
 1476
 1477	return mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp, ul_proto, ul_dip,
 1478						 ul_tb_id, ipip_entry);
 1479}
 1480
 1481/* Given decap parameters, find the corresponding IPIP entry. */
 1482static struct mlxsw_sp_ipip_entry *
 1483mlxsw_sp_ipip_entry_find_by_decap(struct mlxsw_sp *mlxsw_sp, int ul_dev_ifindex,
 1484				  enum mlxsw_sp_l3proto ul_proto,
 1485				  union mlxsw_sp_l3addr ul_dip)
 1486{
 1487	struct mlxsw_sp_ipip_entry *ipip_entry = NULL;
 1488	struct net_device *ul_dev;
 1489
 1490	rcu_read_lock();
 1491
 1492	ul_dev = dev_get_by_index_rcu(mlxsw_sp_net(mlxsw_sp), ul_dev_ifindex);
 1493	if (!ul_dev)
 1494		goto out_unlock;
 1495
 1496	list_for_each_entry(ipip_entry, &mlxsw_sp->router->ipip_list,
 1497			    ipip_list_node)
 1498		if (mlxsw_sp_ipip_entry_matches_decap(mlxsw_sp, ul_dev,
 1499						      ul_proto, ul_dip,
 1500						      ipip_entry))
 1501			goto out_unlock;
 1502
 1503	rcu_read_unlock();
 1504
 1505	return NULL;
 1506
 1507out_unlock:
 1508	rcu_read_unlock();
 1509	return ipip_entry;
 1510}
 1511
 1512static bool mlxsw_sp_netdev_ipip_type(const struct mlxsw_sp *mlxsw_sp,
 1513				      const struct net_device *dev,
 1514				      enum mlxsw_sp_ipip_type *p_type)
 1515{
 1516	struct mlxsw_sp_router *router = mlxsw_sp->router;
 1517	const struct mlxsw_sp_ipip_ops *ipip_ops;
 1518	enum mlxsw_sp_ipip_type ipipt;
 1519
 1520	for (ipipt = 0; ipipt < MLXSW_SP_IPIP_TYPE_MAX; ++ipipt) {
 1521		ipip_ops = router->ipip_ops_arr[ipipt];
 1522		if (dev->type == ipip_ops->dev_type) {
 1523			if (p_type)
 1524				*p_type = ipipt;
 1525			return true;
 1526		}
 1527	}
 1528	return false;
 1529}
 1530
 1531static bool mlxsw_sp_netdev_is_ipip_ol(const struct mlxsw_sp *mlxsw_sp,
 1532				       const struct net_device *dev)
 1533{
 1534	return mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL);
 1535}
 1536
 1537static struct mlxsw_sp_ipip_entry *
 1538mlxsw_sp_ipip_entry_find_by_ol_dev(struct mlxsw_sp *mlxsw_sp,
 1539				   const struct net_device *ol_dev)
 1540{
 1541	struct mlxsw_sp_ipip_entry *ipip_entry;
 1542
 1543	list_for_each_entry(ipip_entry, &mlxsw_sp->router->ipip_list,
 1544			    ipip_list_node)
 1545		if (ipip_entry->ol_dev == ol_dev)
 1546			return ipip_entry;
 1547
 1548	return NULL;
 1549}
 1550
 1551static struct mlxsw_sp_ipip_entry *
 1552mlxsw_sp_ipip_entry_find_by_ul_dev(const struct mlxsw_sp *mlxsw_sp,
 1553				   const struct net_device *ul_dev,
 1554				   struct mlxsw_sp_ipip_entry *start)
 1555{
 1556	struct mlxsw_sp_ipip_entry *ipip_entry;
 1557
 1558	ipip_entry = list_prepare_entry(start, &mlxsw_sp->router->ipip_list,
 1559					ipip_list_node);
 1560	list_for_each_entry_continue(ipip_entry, &mlxsw_sp->router->ipip_list,
 1561				     ipip_list_node) {
 1562		struct net_device *ol_dev = ipip_entry->ol_dev;
 1563		struct net_device *ipip_ul_dev;
 1564
 1565		rcu_read_lock();
 1566		ipip_ul_dev = mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
 1567		rcu_read_unlock();
 1568
 1569		if (ipip_ul_dev == ul_dev)
 1570			return ipip_entry;
 1571	}
 1572
 1573	return NULL;
 1574}
 1575
 1576static bool mlxsw_sp_netdev_is_ipip_ul(struct mlxsw_sp *mlxsw_sp,
 1577				       const struct net_device *dev)
 1578{
 1579	return mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp, dev, NULL);
 1580}
 1581
 1582static bool mlxsw_sp_netdevice_ipip_can_offload(struct mlxsw_sp *mlxsw_sp,
 1583						const struct net_device *ol_dev,
 1584						enum mlxsw_sp_ipip_type ipipt)
 1585{
 1586	const struct mlxsw_sp_ipip_ops *ops
 1587		= mlxsw_sp->router->ipip_ops_arr[ipipt];
 1588
 1589	return ops->can_offload(mlxsw_sp, ol_dev);
 1590}
 1591
 1592static int mlxsw_sp_netdevice_ipip_ol_reg_event(struct mlxsw_sp *mlxsw_sp,
 1593						struct net_device *ol_dev)
 1594{
 1595	enum mlxsw_sp_ipip_type ipipt = MLXSW_SP_IPIP_TYPE_MAX;
 1596	struct mlxsw_sp_ipip_entry *ipip_entry;
 1597	enum mlxsw_sp_l3proto ul_proto;
 1598	union mlxsw_sp_l3addr saddr;
 1599	u32 ul_tb_id;
 1600
 1601	mlxsw_sp_netdev_ipip_type(mlxsw_sp, ol_dev, &ipipt);
 1602	if (mlxsw_sp_netdevice_ipip_can_offload(mlxsw_sp, ol_dev, ipipt)) {
 1603		ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ol_dev);
 1604		ul_proto = mlxsw_sp->router->ipip_ops_arr[ipipt]->ul_proto;
 1605		saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ol_dev);
 1606		if (!mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp, ul_proto,
 1607							  saddr, ul_tb_id,
 1608							  NULL)) {
 1609			ipip_entry = mlxsw_sp_ipip_entry_create(mlxsw_sp, ipipt,
 1610								ol_dev);
 1611			if (IS_ERR(ipip_entry))
 1612				return PTR_ERR(ipip_entry);
 1613		}
 1614	}
 1615
 1616	return 0;
 1617}
 1618
 1619static void mlxsw_sp_netdevice_ipip_ol_unreg_event(struct mlxsw_sp *mlxsw_sp,
 1620						   struct net_device *ol_dev)
 1621{
 1622	struct mlxsw_sp_ipip_entry *ipip_entry;
 1623
 1624	ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
 1625	if (ipip_entry)
 1626		mlxsw_sp_ipip_entry_destroy(mlxsw_sp, ipip_entry);
 1627}
 1628
 1629static void
 1630mlxsw_sp_ipip_entry_ol_up_event(struct mlxsw_sp *mlxsw_sp,
 1631				struct mlxsw_sp_ipip_entry *ipip_entry)
 1632{
 1633	struct mlxsw_sp_fib_entry *decap_fib_entry;
 1634
 1635	decap_fib_entry = mlxsw_sp_ipip_entry_find_decap(mlxsw_sp, ipip_entry);
 1636	if (decap_fib_entry)
 1637		mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp, ipip_entry,
 1638						  decap_fib_entry);
 1639}
 1640
 1641static int
 1642mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id,
 1643			u16 ul_rif_id, bool enable)
 1644{
 1645	struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config;
 1646	struct net_device *dev = mlxsw_sp_rif_dev(&lb_rif->common);
 1647	enum mlxsw_reg_ritr_loopback_ipip_options ipip_options;
 1648	struct mlxsw_sp_rif *rif = &lb_rif->common;
 1649	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
 1650	char ritr_pl[MLXSW_REG_RITR_LEN];
 1651	struct in6_addr *saddr6;
 1652	u32 saddr4;
 1653
 1654	ipip_options = MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET;
 1655	switch (lb_cf.ul_protocol) {
 1656	case MLXSW_SP_L3_PROTO_IPV4:
 1657		saddr4 = be32_to_cpu(lb_cf.saddr.addr4);
 1658		mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
 1659				    rif->rif_index, rif->vr_id, dev->mtu);
 1660		mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt,
 1661						   ipip_options, ul_vr_id,
 1662						   ul_rif_id, saddr4,
 1663						   lb_cf.okey);
 1664		break;
 1665
 1666	case MLXSW_SP_L3_PROTO_IPV6:
 1667		saddr6 = &lb_cf.saddr.addr6;
 1668		mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
 1669				    rif->rif_index, rif->vr_id, dev->mtu);
 1670		mlxsw_reg_ritr_loopback_ipip6_pack(ritr_pl, lb_cf.lb_ipipt,
 1671						   ipip_options, ul_vr_id,
 1672						   ul_rif_id, saddr6,
 1673						   lb_cf.okey);
 1674		break;
 1675	}
 1676
 1677	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
 1678}
 1679
 1680static int mlxsw_sp_netdevice_ipip_ol_update_mtu(struct mlxsw_sp *mlxsw_sp,
 1681						 struct net_device *ol_dev)
 1682{
 1683	struct mlxsw_sp_ipip_entry *ipip_entry;
 1684	struct mlxsw_sp_rif_ipip_lb *lb_rif;
 1685	int err = 0;
 1686
 1687	ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
 1688	if (ipip_entry) {
 1689		lb_rif = ipip_entry->ol_lb;
 1690		err = mlxsw_sp_rif_ipip_lb_op(lb_rif, lb_rif->ul_vr_id,
 1691					      lb_rif->ul_rif_id, true);
 1692		if (err)
 1693			goto out;
 1694		lb_rif->common.mtu = ol_dev->mtu;
 1695	}
 1696
 1697out:
 1698	return err;
 1699}
 1700
 1701static void mlxsw_sp_netdevice_ipip_ol_up_event(struct mlxsw_sp *mlxsw_sp,
 1702						struct net_device *ol_dev)
 1703{
 1704	struct mlxsw_sp_ipip_entry *ipip_entry;
 1705
 1706	ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
 1707	if (ipip_entry)
 1708		mlxsw_sp_ipip_entry_ol_up_event(mlxsw_sp, ipip_entry);
 1709}
 1710
 1711static void
 1712mlxsw_sp_ipip_entry_ol_down_event(struct mlxsw_sp *mlxsw_sp,
 1713				  struct mlxsw_sp_ipip_entry *ipip_entry)
 1714{
 1715	if (ipip_entry->decap_fib_entry)
 1716		mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
 1717}
 1718
 1719static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp *mlxsw_sp,
 1720						  struct net_device *ol_dev)
 1721{
 1722	struct mlxsw_sp_ipip_entry *ipip_entry;
 1723
 1724	ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
 1725	if (ipip_entry)
 1726		mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp, ipip_entry);
 1727}
 1728
 1729static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
 1730					struct mlxsw_sp_rif *rif);
 1731
 1732static void mlxsw_sp_rif_migrate_destroy(struct mlxsw_sp *mlxsw_sp,
 1733					 struct mlxsw_sp_rif *old_rif,
 1734					 struct mlxsw_sp_rif *new_rif,
 1735					 bool migrate_nhs)
 1736{
 1737	struct mlxsw_sp_crif *crif = old_rif->crif;
 1738	struct mlxsw_sp_crif mock_crif = {};
 1739
 1740	if (migrate_nhs)
 1741		mlxsw_sp_nexthop_rif_update(mlxsw_sp, new_rif);
 1742
 1743	/* Plant a mock CRIF so that destroying the old RIF doesn't unoffload
 1744	 * our nexthops and IPIP tunnels, and doesn't sever the crif->rif link.
 1745	 */
 1746	mlxsw_sp_crif_init(&mock_crif, crif->key.dev);
 1747	old_rif->crif = &mock_crif;
 1748	mock_crif.rif = old_rif;
 1749	mlxsw_sp_rif_destroy(old_rif);
 1750}
 1751
 1752static int
 1753mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp,
 1754				 struct mlxsw_sp_ipip_entry *ipip_entry,
 1755				 bool keep_encap,
 1756				 struct netlink_ext_ack *extack)
 1757{
 1758	struct mlxsw_sp_rif_ipip_lb *old_lb_rif = ipip_entry->ol_lb;
 1759	struct mlxsw_sp_rif_ipip_lb *new_lb_rif;
 1760
 1761	new_lb_rif = mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp,
 1762						     ipip_entry->ipipt,
 1763						     ipip_entry->ol_dev,
 1764						     extack);
 1765	if (IS_ERR(new_lb_rif))
 1766		return PTR_ERR(new_lb_rif);
 1767	ipip_entry->ol_lb = new_lb_rif;
 1768
 1769	mlxsw_sp_rif_migrate_destroy(mlxsw_sp, &old_lb_rif->common,
 1770				     &new_lb_rif->common, keep_encap);
 1771	return 0;
 1772}
 1773
 1774/**
 1775 * __mlxsw_sp_ipip_entry_update_tunnel - Update offload related to IPIP entry.
 1776 * @mlxsw_sp: mlxsw_sp.
 1777 * @ipip_entry: IPIP entry.
 1778 * @recreate_loopback: Recreates the associated loopback RIF.
 1779 * @keep_encap: Updates next hops that use the tunnel netdevice. This is only
 1780 *              relevant when recreate_loopback is true.
 1781 * @update_nexthops: Updates next hops, keeping the current loopback RIF. This
 1782 *                   is only relevant when recreate_loopback is false.
 1783 * @extack: extack.
 1784 *
 1785 * Return: Non-zero value on failure.
 1786 */
 1787int __mlxsw_sp_ipip_entry_update_tunnel(struct mlxsw_sp *mlxsw_sp,
 1788					struct mlxsw_sp_ipip_entry *ipip_entry,
 1789					bool recreate_loopback,
 1790					bool keep_encap,
 1791					bool update_nexthops,
 1792					struct netlink_ext_ack *extack)
 1793{
 1794	int err;
 1795
 1796	/* RIFs can't be edited, so to update loopback, we need to destroy and
 1797	 * recreate it. That creates a window of opportunity where RALUE and
 1798	 * RATR registers end up referencing a RIF that's already gone. RATRs
 1799	 * are handled in mlxsw_sp_ipip_entry_ol_lb_update(), and to take care
 1800	 * of RALUE, demote the decap route back.
 1801	 */
 1802	if (ipip_entry->decap_fib_entry)
 1803		mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
 1804
 1805	if (recreate_loopback) {
 1806		err = mlxsw_sp_ipip_entry_ol_lb_update(mlxsw_sp, ipip_entry,
 1807						       keep_encap, extack);
 1808		if (err)
 1809			return err;
 1810	} else if (update_nexthops) {
 1811		mlxsw_sp_nexthop_rif_update(mlxsw_sp,
 1812					    &ipip_entry->ol_lb->common);
 1813	}
 1814
 1815	if (ipip_entry->ol_dev->flags & IFF_UP)
 1816		mlxsw_sp_ipip_entry_ol_up_event(mlxsw_sp, ipip_entry);
 1817
 1818	return 0;
 1819}
 1820
 1821static int mlxsw_sp_netdevice_ipip_ol_vrf_event(struct mlxsw_sp *mlxsw_sp,
 1822						struct net_device *ol_dev,
 1823						struct netlink_ext_ack *extack)
 1824{
 1825	struct mlxsw_sp_ipip_entry *ipip_entry =
 1826		mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
 1827
 1828	if (!ipip_entry)
 1829		return 0;
 1830
 1831	return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
 1832						   true, false, false, extack);
 1833}
 1834
 1835static int
 1836mlxsw_sp_netdevice_ipip_ul_vrf_event(struct mlxsw_sp *mlxsw_sp,
 1837				     struct mlxsw_sp_ipip_entry *ipip_entry,
 1838				     struct net_device *ul_dev,
 1839				     bool *demote_this,
 1840				     struct netlink_ext_ack *extack)
 1841{
 1842	u32 ul_tb_id = l3mdev_fib_table(ul_dev) ? : RT_TABLE_MAIN;
 1843	enum mlxsw_sp_l3proto ul_proto;
 1844	union mlxsw_sp_l3addr saddr;
 1845
 1846	/* Moving underlay to a different VRF might cause local address
 1847	 * conflict, and the conflicting tunnels need to be demoted.
 1848	 */
 1849	ul_proto = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt]->ul_proto;
 1850	saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ipip_entry->ol_dev);
 1851	if (mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp, ul_proto,
 1852						 saddr, ul_tb_id,
 1853						 ipip_entry)) {
 1854		*demote_this = true;
 1855		return 0;
 1856	}
 1857
 1858	return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
 1859						   true, true, false, extack);
 1860}
 1861
 1862static int
 1863mlxsw_sp_netdevice_ipip_ul_up_event(struct mlxsw_sp *mlxsw_sp,
 1864				    struct mlxsw_sp_ipip_entry *ipip_entry,
 1865				    struct net_device *ul_dev)
 1866{
 1867	return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
 1868						   false, false, true, NULL);
 1869}
 1870
 1871static int
 1872mlxsw_sp_netdevice_ipip_ul_down_event(struct mlxsw_sp *mlxsw_sp,
 1873				      struct mlxsw_sp_ipip_entry *ipip_entry,
 1874				      struct net_device *ul_dev)
 1875{
 1876	/* A down underlay device causes encapsulated packets to not be
 1877	 * forwarded, but decap still works. So refresh next hops without
 1878	 * touching anything else.
 1879	 */
 1880	return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
 1881						   false, false, true, NULL);
 1882}
 1883
 1884static int
 1885mlxsw_sp_netdevice_ipip_ol_change_event(struct mlxsw_sp *mlxsw_sp,
 1886					struct net_device *ol_dev,
 1887					struct netlink_ext_ack *extack)
 1888{
 1889	const struct mlxsw_sp_ipip_ops *ipip_ops;
 1890	struct mlxsw_sp_ipip_entry *ipip_entry;
 1891	int err;
 1892
 1893	ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
 1894	if (!ipip_entry)
 1895		/* A change might make a tunnel eligible for offloading, but
 1896		 * that is currently not implemented. What falls to slow path
 1897		 * stays there.
 1898		 */
 1899		return 0;
 1900
 1901	/* A change might make a tunnel not eligible for offloading. */
 1902	if (!mlxsw_sp_netdevice_ipip_can_offload(mlxsw_sp, ol_dev,
 1903						 ipip_entry->ipipt)) {
 1904		mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
 1905		return 0;
 1906	}
 1907
 1908	ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
 1909	err = ipip_ops->ol_netdev_change(mlxsw_sp, ipip_entry, extack);
 1910	return err;
 1911}
 1912
 1913void mlxsw_sp_ipip_entry_demote_tunnel(struct mlxsw_sp *mlxsw_sp,
 1914				       struct mlxsw_sp_ipip_entry *ipip_entry)
 1915{
 1916	struct net_device *ol_dev = ipip_entry->ol_dev;
 1917
 1918	if (ol_dev->flags & IFF_UP)
 1919		mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp, ipip_entry);
 1920	mlxsw_sp_ipip_entry_destroy(mlxsw_sp, ipip_entry);
 1921}
 1922
 1923/* The configuration where several tunnels have the same local address in the
 1924 * same underlay table needs special treatment in the HW. That is currently not
 1925 * implemented in the driver. This function finds and demotes the first tunnel
 1926 * with a given source address, except the one passed in the argument
 1927 * `except'.
 1928 */
 1929bool
 1930mlxsw_sp_ipip_demote_tunnel_by_saddr(struct mlxsw_sp *mlxsw_sp,
 1931				     enum mlxsw_sp_l3proto ul_proto,
 1932				     union mlxsw_sp_l3addr saddr,
 1933				     u32 ul_tb_id,
 1934				     const struct mlxsw_sp_ipip_entry *except)
 1935{
 1936	struct mlxsw_sp_ipip_entry *ipip_entry, *tmp;
 1937
 1938	list_for_each_entry_safe(ipip_entry, tmp, &mlxsw_sp->router->ipip_list,
 1939				 ipip_list_node) {
 1940		if (ipip_entry != except &&
 1941		    mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp, ul_proto, saddr,
 1942						      ul_tb_id, ipip_entry)) {
 1943			mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
 1944			return true;
 1945		}
 1946	}
 1947
 1948	return false;
 1949}
 1950
 1951static void mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(struct mlxsw_sp *mlxsw_sp,
 1952						     struct net_device *ul_dev)
 1953{
 1954	struct mlxsw_sp_ipip_entry *ipip_entry, *tmp;
 1955
 1956	list_for_each_entry_safe(ipip_entry, tmp, &mlxsw_sp->router->ipip_list,
 1957				 ipip_list_node) {
 1958		struct net_device *ol_dev = ipip_entry->ol_dev;
 1959		struct net_device *ipip_ul_dev;
 1960
 1961		rcu_read_lock();
 1962		ipip_ul_dev = mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
 1963		rcu_read_unlock();
 1964		if (ipip_ul_dev == ul_dev)
 1965			mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
 1966	}
 1967}
 1968
 1969static int mlxsw_sp_netdevice_ipip_ol_event(struct mlxsw_sp *mlxsw_sp,
 1970					    struct net_device *ol_dev,
 1971					    unsigned long event,
 1972					    struct netdev_notifier_info *info)
 1973{
 1974	struct netdev_notifier_changeupper_info *chup;
 1975	struct netlink_ext_ack *extack;
 1976	int err = 0;
 1977
 1978	switch (event) {
 1979	case NETDEV_REGISTER:
 1980		err = mlxsw_sp_netdevice_ipip_ol_reg_event(mlxsw_sp, ol_dev);
 1981		break;
 1982	case NETDEV_UNREGISTER:
 1983		mlxsw_sp_netdevice_ipip_ol_unreg_event(mlxsw_sp, ol_dev);
 1984		break;
 1985	case NETDEV_UP:
 1986		mlxsw_sp_netdevice_ipip_ol_up_event(mlxsw_sp, ol_dev);
 1987		break;
 1988	case NETDEV_DOWN:
 1989		mlxsw_sp_netdevice_ipip_ol_down_event(mlxsw_sp, ol_dev);
 1990		break;
 1991	case NETDEV_CHANGEUPPER:
 1992		chup = container_of(info, typeof(*chup), info);
 1993		extack = info->extack;
 1994		if (netif_is_l3_master(chup->upper_dev))
 1995			err = mlxsw_sp_netdevice_ipip_ol_vrf_event(mlxsw_sp,
 1996								   ol_dev,
 1997								   extack);
 1998		break;
 1999	case NETDEV_CHANGE:
 2000		extack = info->extack;
 2001		err = mlxsw_sp_netdevice_ipip_ol_change_event(mlxsw_sp,
 2002							      ol_dev, extack);
 2003		break;
 2004	case NETDEV_CHANGEMTU:
 2005		err = mlxsw_sp_netdevice_ipip_ol_update_mtu(mlxsw_sp, ol_dev);
 2006		break;
 2007	}
 2008	return err;
 2009}
 2010
 2011static int
 2012__mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
 2013				   struct mlxsw_sp_ipip_entry *ipip_entry,
 2014				   struct net_device *ul_dev,
 2015				   bool *demote_this,
 2016				   unsigned long event,
 2017				   struct netdev_notifier_info *info)
 2018{
 2019	struct netdev_notifier_changeupper_info *chup;
 2020	struct netlink_ext_ack *extack;
 2021
 2022	switch (event) {
 2023	case NETDEV_CHANGEUPPER:
 2024		chup = container_of(info, typeof(*chup), info);
 2025		extack = info->extack;
 2026		if (netif_is_l3_master(chup->upper_dev))
 2027			return mlxsw_sp_netdevice_ipip_ul_vrf_event(mlxsw_sp,
 2028								    ipip_entry,
 2029								    ul_dev,
 2030								    demote_this,
 2031								    extack);
 2032		break;
 2033
 2034	case NETDEV_UP:
 2035		return mlxsw_sp_netdevice_ipip_ul_up_event(mlxsw_sp, ipip_entry,
 2036							   ul_dev);
 2037	case NETDEV_DOWN:
 2038		return mlxsw_sp_netdevice_ipip_ul_down_event(mlxsw_sp,
 2039							     ipip_entry,
 2040							     ul_dev);
 2041	}
 2042	return 0;
 2043}
 2044
 2045static int
 2046mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
 2047				 struct net_device *ul_dev,
 2048				 unsigned long event,
 2049				 struct netdev_notifier_info *info)
 2050{
 2051	struct mlxsw_sp_ipip_entry *ipip_entry = NULL;
 2052	int err;
 2053
 2054	while ((ipip_entry = mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp,
 2055								ul_dev,
 2056								ipip_entry))) {
 2057		struct mlxsw_sp_ipip_entry *prev;
 2058		bool demote_this = false;
 2059
 2060		err = __mlxsw_sp_netdevice_ipip_ul_event(mlxsw_sp, ipip_entry,
 2061							 ul_dev, &demote_this,
 2062							 event, info);
 2063		if (err) {
 2064			mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(mlxsw_sp,
 2065								 ul_dev);
 2066			return err;
 2067		}
 2068
 2069		if (demote_this) {
 2070			if (list_is_first(&ipip_entry->ipip_list_node,
 2071					  &mlxsw_sp->router->ipip_list))
 2072				prev = NULL;
 2073			else
 2074				/* This can't be cached from previous iteration,
 2075				 * because that entry could be gone now.
 2076				 */
 2077				prev = list_prev_entry(ipip_entry,
 2078						       ipip_list_node);
 2079			mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
 2080			ipip_entry = prev;
 2081		}
 2082	}
 2083
 2084	return 0;
 2085}
 2086
 2087int mlxsw_sp_router_nve_promote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
 2088				      enum mlxsw_sp_l3proto ul_proto,
 2089				      const union mlxsw_sp_l3addr *ul_sip,
 2090				      u32 tunnel_index)
 2091{
 2092	enum mlxsw_sp_fib_entry_type type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
 2093	struct mlxsw_sp_router *router = mlxsw_sp->router;
 2094	struct mlxsw_sp_fib_entry *fib_entry;
 2095	int err = 0;
 2096
 2097	mutex_lock(&mlxsw_sp->router->lock);
 2098
 2099	if (WARN_ON_ONCE(router->nve_decap_config.valid)) {
 2100		err = -EINVAL;
 2101		goto out;
 2102	}
 2103
 2104	router->nve_decap_config.ul_tb_id = ul_tb_id;
 2105	router->nve_decap_config.tunnel_index = tunnel_index;
 2106	router->nve_decap_config.ul_proto = ul_proto;
 2107	router->nve_decap_config.ul_sip = *ul_sip;
 2108	router->nve_decap_config.valid = true;
 2109
 2110	/* It is valid to create a tunnel with a local IP and only later
 2111	 * assign this IP address to a local interface
 2112	 */
 2113	fib_entry = mlxsw_sp_router_ip2me_fib_entry_find(mlxsw_sp, ul_tb_id,
 2114							 ul_proto, ul_sip,
 2115							 type);
 2116	if (!fib_entry)
 2117		goto out;
 2118
 2119	fib_entry->decap.tunnel_index = tunnel_index;
 2120	fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP;
 2121
 2122	err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
 2123	if (err)
 2124		goto err_fib_entry_update;
 2125
 2126	goto out;
 2127
 2128err_fib_entry_update:
 2129	fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
 2130	mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
 2131out:
 2132	mutex_unlock(&mlxsw_sp->router->lock);
 2133	return err;
 2134}
 2135
 2136void mlxsw_sp_router_nve_demote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
 2137				      enum mlxsw_sp_l3proto ul_proto,
 2138				      const union mlxsw_sp_l3addr *ul_sip)
 2139{
 2140	enum mlxsw_sp_fib_entry_type type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP;
 2141	struct mlxsw_sp_router *router = mlxsw_sp->router;
 2142	struct mlxsw_sp_fib_entry *fib_entry;
 2143
 2144	mutex_lock(&mlxsw_sp->router->lock);
 2145
 2146	if (WARN_ON_ONCE(!router->nve_decap_config.valid))
 2147		goto out;
 2148
 2149	router->nve_decap_config.valid = false;
 2150
 2151	fib_entry = mlxsw_sp_router_ip2me_fib_entry_find(mlxsw_sp, ul_tb_id,
 2152							 ul_proto, ul_sip,
 2153							 type);
 2154	if (!fib_entry)
 2155		goto out;
 2156
 2157	fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
 2158	mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
 2159out:
 2160	mutex_unlock(&mlxsw_sp->router->lock);
 2161}
 2162
 2163static bool mlxsw_sp_router_nve_is_decap(struct mlxsw_sp *mlxsw_sp,
 2164					 u32 ul_tb_id,
 2165					 enum mlxsw_sp_l3proto ul_proto,
 2166					 const union mlxsw_sp_l3addr *ul_sip)
 2167{
 2168	struct mlxsw_sp_router *router = mlxsw_sp->router;
 2169
 2170	return router->nve_decap_config.valid &&
 2171	       router->nve_decap_config.ul_tb_id == ul_tb_id &&
 2172	       router->nve_decap_config.ul_proto == ul_proto &&
 2173	       !memcmp(&router->nve_decap_config.ul_sip, ul_sip,
 2174		       sizeof(*ul_sip));
 2175}
 2176
 2177struct mlxsw_sp_neigh_key {
 2178	struct neighbour *n;
 2179};
 2180
 2181struct mlxsw_sp_neigh_entry {
 2182	struct list_head rif_list_node;
 2183	struct rhash_head ht_node;
 2184	struct mlxsw_sp_neigh_key key;
 2185	u16 rif;
 2186	bool connected;
 2187	unsigned char ha[ETH_ALEN];
 2188	struct list_head nexthop_list; /* list of nexthops using
 2189					* this neigh entry
 2190					*/
 2191	struct list_head nexthop_neighs_list_node;
 2192	unsigned int counter_index;
 2193	bool counter_valid;
 2194};
 2195
 2196static const struct rhashtable_params mlxsw_sp_neigh_ht_params = {
 2197	.key_offset = offsetof(struct mlxsw_sp_neigh_entry, key),
 2198	.head_offset = offsetof(struct mlxsw_sp_neigh_entry, ht_node),
 2199	.key_len = sizeof(struct mlxsw_sp_neigh_key),
 2200};
 2201
 2202struct mlxsw_sp_neigh_entry *
 2203mlxsw_sp_rif_neigh_next(struct mlxsw_sp_rif *rif,
 2204			struct mlxsw_sp_neigh_entry *neigh_entry)
 2205{
 2206	if (!neigh_entry) {
 2207		if (list_empty(&rif->neigh_list))
 2208			return NULL;
 2209		else
 2210			return list_first_entry(&rif->neigh_list,
 2211						typeof(*neigh_entry),
 2212						rif_list_node);
 2213	}
 2214	if (list_is_last(&neigh_entry->rif_list_node, &rif->neigh_list))
 2215		return NULL;
 2216	return list_next_entry(neigh_entry, rif_list_node);
 2217}
 2218
 2219int mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry *neigh_entry)
 2220{
 2221	return neigh_entry->key.n->tbl->family;
 2222}
 2223
 2224unsigned char *
 2225mlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry *neigh_entry)
 2226{
 2227	return neigh_entry->ha;
 2228}
 2229
 2230u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
 2231{
 2232	struct neighbour *n;
 2233
 2234	n = neigh_entry->key.n;
 2235	return ntohl(*((__be32 *) n->primary_key));
 2236}
 2237
 2238struct in6_addr *
 2239mlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
 2240{
 2241	struct neighbour *n;
 2242
 2243	n = neigh_entry->key.n;
 2244	return (struct in6_addr *) &n->primary_key;
 2245}
 2246
 2247int mlxsw_sp_neigh_counter_get(struct mlxsw_sp *mlxsw_sp,
 2248			       struct mlxsw_sp_neigh_entry *neigh_entry,
 2249			       u64 *p_counter)
 2250{
 2251	if (!neigh_entry->counter_valid)
 2252		return -EINVAL;
 2253
 2254	return mlxsw_sp_flow_counter_get(mlxsw_sp, neigh_entry->counter_index,
 2255					 false, p_counter, NULL);
 2256}
 2257
 2258static struct mlxsw_sp_neigh_entry *
 2259mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n,
 2260			   u16 rif)
 2261{
 2262	struct mlxsw_sp_neigh_entry *neigh_entry;
 2263
 2264	neigh_entry = kzalloc(sizeof(*neigh_entry), GFP_KERNEL);
 2265	if (!neigh_entry)
 2266		return NULL;
 2267
 2268	neigh_hold(n);
 2269	neigh_entry->key.n = n;
 2270	neigh_entry->rif = rif;
 2271	INIT_LIST_HEAD(&neigh_entry->nexthop_list);
 2272
 2273	return neigh_entry;
 2274}
 2275
 2276static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry)
 2277{
 2278	neigh_release(neigh_entry->key.n);
 2279	kfree(neigh_entry);
 2280}
 2281
 2282static int
 2283mlxsw_sp_neigh_entry_insert(struct mlxsw_sp *mlxsw_sp,
 2284			    struct mlxsw_sp_neigh_entry *neigh_entry)
 2285{
 2286	return rhashtable_insert_fast(&mlxsw_sp->router->neigh_ht,
 2287				      &neigh_entry->ht_node,
 2288				      mlxsw_sp_neigh_ht_params);
 2289}
 2290
 2291static void
 2292mlxsw_sp_neigh_entry_remove(struct mlxsw_sp *mlxsw_sp,
 2293			    struct mlxsw_sp_neigh_entry *neigh_entry)
 2294{
 2295	rhashtable_remove_fast(&mlxsw_sp->router->neigh_ht,
 2296			       &neigh_entry->ht_node,
 2297			       mlxsw_sp_neigh_ht_params);
 2298}
 2299
 2300static bool
 2301mlxsw_sp_neigh_counter_should_alloc(struct mlxsw_sp *mlxsw_sp,
 2302				    struct mlxsw_sp_neigh_entry *neigh_entry)
 2303{
 2304	struct devlink *devlink;
 2305	const char *table_name;
 2306
 2307	switch (mlxsw_sp_neigh_entry_type(neigh_entry)) {
 2308	case AF_INET:
 2309		table_name = MLXSW_SP_DPIPE_TABLE_NAME_HOST4;
 2310		break;
 2311	case AF_INET6:
 2312		table_name = MLXSW_SP_DPIPE_TABLE_NAME_HOST6;
 2313		break;
 2314	default:
 2315		WARN_ON(1);
 2316		return false;
 2317	}
 2318
 2319	devlink = priv_to_devlink(mlxsw_sp->core);
 2320	return devlink_dpipe_table_counter_enabled(devlink, table_name);
 2321}
 2322
 2323static void
 2324mlxsw_sp_neigh_counter_alloc(struct mlxsw_sp *mlxsw_sp,
 2325			     struct mlxsw_sp_neigh_entry *neigh_entry)
 2326{
 2327	if (!mlxsw_sp_neigh_counter_should_alloc(mlxsw_sp, neigh_entry))
 2328		return;
 2329
 2330	if (mlxsw_sp_flow_counter_alloc(mlxsw_sp, &neigh_entry->counter_index))
 2331		return;
 2332
 2333	neigh_entry->counter_valid = true;
 2334}
 2335
 2336static void
 2337mlxsw_sp_neigh_counter_free(struct mlxsw_sp *mlxsw_sp,
 2338			    struct mlxsw_sp_neigh_entry *neigh_entry)
 2339{
 2340	if (!neigh_entry->counter_valid)
 2341		return;
 2342	mlxsw_sp_flow_counter_free(mlxsw_sp,
 2343				   neigh_entry->counter_index);
 2344	neigh_entry->counter_valid = false;
 2345}
 2346
 2347static struct mlxsw_sp_neigh_entry *
 2348mlxsw_sp_neigh_entry_create(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
 2349{
 2350	struct mlxsw_sp_neigh_entry *neigh_entry;
 2351	struct mlxsw_sp_rif *rif;
 2352	int err;
 2353
 2354	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, n->dev);
 2355	if (!rif)
 2356		return ERR_PTR(-EINVAL);
 2357
 2358	neigh_entry = mlxsw_sp_neigh_entry_alloc(mlxsw_sp, n, rif->rif_index);
 2359	if (!neigh_entry)
 2360		return ERR_PTR(-ENOMEM);
 2361
 2362	err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
 2363	if (err)
 2364		goto err_neigh_entry_insert;
 2365
 2366	mlxsw_sp_neigh_counter_alloc(mlxsw_sp, neigh_entry);
 2367	atomic_inc(&mlxsw_sp->router->neighs_update.neigh_count);
 2368	list_add(&neigh_entry->rif_list_node, &rif->neigh_list);
 2369
 2370	return neigh_entry;
 2371
 2372err_neigh_entry_insert:
 2373	mlxsw_sp_neigh_entry_free(neigh_entry);
 2374	return ERR_PTR(err);
 2375}
 2376
 2377static void
 2378mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp *mlxsw_sp,
 2379			     struct mlxsw_sp_neigh_entry *neigh_entry)
 2380{
 2381	list_del(&neigh_entry->rif_list_node);
 2382	atomic_dec(&mlxsw_sp->router->neighs_update.neigh_count);
 2383	mlxsw_sp_neigh_counter_free(mlxsw_sp, neigh_entry);
 2384	mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry);
 2385	mlxsw_sp_neigh_entry_free(neigh_entry);
 2386}
 2387
 2388static struct mlxsw_sp_neigh_entry *
 2389mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
 2390{
 2391	struct mlxsw_sp_neigh_key key;
 2392
 2393	key.n = n;
 2394	return rhashtable_lookup_fast(&mlxsw_sp->router->neigh_ht,
 2395				      &key, mlxsw_sp_neigh_ht_params);
 2396}
 2397
 2398static void
 2399mlxsw_sp_router_neighs_update_interval_init(struct mlxsw_sp *mlxsw_sp)
 2400{
 2401	unsigned long interval;
 2402
 2403#if IS_ENABLED(CONFIG_IPV6)
 2404	interval = min_t(unsigned long,
 2405			 NEIGH_VAR(&arp_tbl.parms, DELAY_PROBE_TIME),
 2406			 NEIGH_VAR(&nd_tbl.parms, DELAY_PROBE_TIME));
 2407#else
 2408	interval = NEIGH_VAR(&arp_tbl.parms, DELAY_PROBE_TIME);
 2409#endif
 2410	mlxsw_sp->router->neighs_update.interval = jiffies_to_msecs(interval);
 2411}
 2412
 2413static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp,
 2414						   char *rauhtd_pl,
 2415						   int ent_index)
 2416{
 2417	u64 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
 2418	struct net_device *dev;
 2419	struct neighbour *n;
 2420	__be32 dipn;
 2421	u32 dip;
 2422	u16 rif;
 2423
 2424	mlxsw_reg_rauhtd_ent_ipv4_unpack(rauhtd_pl, ent_index, &rif, &dip);
 2425
 2426	if (WARN_ON_ONCE(rif >= max_rifs))
 2427		return;
 2428	if (!mlxsw_sp->router->rifs[rif]) {
 2429		dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n");
 2430		return;
 2431	}
 2432
 2433	dipn = htonl(dip);
 2434	dev = mlxsw_sp_rif_dev(mlxsw_sp->router->rifs[rif]);
 2435	n = neigh_lookup(&arp_tbl, &dipn, dev);
 2436	if (!n)
 2437		return;
 2438
 2439	netdev_dbg(dev, "Updating neighbour with IP=%pI4h\n", &dip);
 2440	neigh_event_send(n, NULL);
 2441	neigh_release(n);
 2442}
 2443
 2444#if IS_ENABLED(CONFIG_IPV6)
 2445static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
 2446						   char *rauhtd_pl,
 2447						   int rec_index)
 2448{
 2449	struct net_device *dev;
 2450	struct neighbour *n;
 2451	struct in6_addr dip;
 2452	u16 rif;
 2453
 2454	mlxsw_reg_rauhtd_ent_ipv6_unpack(rauhtd_pl, rec_index, &rif,
 2455					 (char *) &dip);
 2456
 2457	if (!mlxsw_sp->router->rifs[rif]) {
 2458		dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n");
 2459		return;
 2460	}
 2461
 2462	dev = mlxsw_sp_rif_dev(mlxsw_sp->router->rifs[rif]);
 2463	n = neigh_lookup(&nd_tbl, &dip, dev);
 2464	if (!n)
 2465		return;
 2466
 2467	netdev_dbg(dev, "Updating neighbour with IP=%pI6c\n", &dip);
 2468	neigh_event_send(n, NULL);
 2469	neigh_release(n);
 2470}
 2471#else
 2472static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
 2473						   char *rauhtd_pl,
 2474						   int rec_index)
 2475{
 2476}
 2477#endif
 2478
 2479static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp *mlxsw_sp,
 2480						   char *rauhtd_pl,
 2481						   int rec_index)
 2482{
 2483	u8 num_entries;
 2484	int i;
 2485
 2486	num_entries = mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl,
 2487								rec_index);
 2488	/* Hardware starts counting at 0, so add 1. */
 2489	num_entries++;
 2490
 2491	/* Each record consists of several neighbour entries. */
 2492	for (i = 0; i < num_entries; i++) {
 2493		int ent_index;
 2494
 2495		ent_index = rec_index * MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC + i;
 2496		mlxsw_sp_router_neigh_ent_ipv4_process(mlxsw_sp, rauhtd_pl,
 2497						       ent_index);
 2498	}
 2499
 2500}
 2501
 2502static void mlxsw_sp_router_neigh_rec_ipv6_process(struct mlxsw_sp *mlxsw_sp,
 2503						   char *rauhtd_pl,
 2504						   int rec_index)
 2505{
 2506	/* One record contains one entry. */
 2507	mlxsw_sp_router_neigh_ent_ipv6_process(mlxsw_sp, rauhtd_pl,
 2508					       rec_index);
 2509}
 2510
 2511static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp *mlxsw_sp,
 2512					      char *rauhtd_pl, int rec_index)
 2513{
 2514	switch (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl, rec_index)) {
 2515	case MLXSW_REG_RAUHTD_TYPE_IPV4:
 2516		mlxsw_sp_router_neigh_rec_ipv4_process(mlxsw_sp, rauhtd_pl,
 2517						       rec_index);
 2518		break;
 2519	case MLXSW_REG_RAUHTD_TYPE_IPV6:
 2520		mlxsw_sp_router_neigh_rec_ipv6_process(mlxsw_sp, rauhtd_pl,
 2521						       rec_index);
 2522		break;
 2523	}
 2524}
 2525
 2526static bool mlxsw_sp_router_rauhtd_is_full(char *rauhtd_pl)
 2527{
 2528	u8 num_rec, last_rec_index, num_entries;
 2529
 2530	num_rec = mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl);
 2531	last_rec_index = num_rec - 1;
 2532
 2533	if (num_rec < MLXSW_REG_RAUHTD_REC_MAX_NUM)
 2534		return false;
 2535	if (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl, last_rec_index) ==
 2536	    MLXSW_REG_RAUHTD_TYPE_IPV6)
 2537		return true;
 2538
 2539	num_entries = mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl,
 2540								last_rec_index);
 2541	if (++num_entries == MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC)
 2542		return true;
 2543	return false;
 2544}
 2545
 2546static int
 2547__mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp,
 2548				       char *rauhtd_pl,
 2549				       enum mlxsw_reg_rauhtd_type type)
 2550{
 2551	int i, num_rec;
 2552	int err;
 2553
 2554	/* Ensure the RIF we read from the device does not change mid-dump. */
 2555	mutex_lock(&mlxsw_sp->router->lock);
 2556	do {
 2557		mlxsw_reg_rauhtd_pack(rauhtd_pl, type);
 2558		err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(rauhtd),
 2559				      rauhtd_pl);
 2560		if (err) {
 2561			dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to dump neighbour table\n");
 2562			break;
 2563		}
 2564		num_rec = mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl);
 2565		for (i = 0; i < num_rec; i++)
 2566			mlxsw_sp_router_neigh_rec_process(mlxsw_sp, rauhtd_pl,
 2567							  i);
 2568	} while (mlxsw_sp_router_rauhtd_is_full(rauhtd_pl));
 2569	mutex_unlock(&mlxsw_sp->router->lock);
 2570
 2571	return err;
 2572}
 2573
 2574static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp)
 2575{
 2576	enum mlxsw_reg_rauhtd_type type;
 2577	char *rauhtd_pl;
 2578	int err;
 2579
 2580	if (!atomic_read(&mlxsw_sp->router->neighs_update.neigh_count))
 2581		return 0;
 2582
 2583	rauhtd_pl = kmalloc(MLXSW_REG_RAUHTD_LEN, GFP_KERNEL);
 2584	if (!rauhtd_pl)
 2585		return -ENOMEM;
 2586
 2587	type = MLXSW_REG_RAUHTD_TYPE_IPV4;
 2588	err = __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp, rauhtd_pl, type);
 2589	if (err)
 2590		goto out;
 2591
 2592	type = MLXSW_REG_RAUHTD_TYPE_IPV6;
 2593	err = __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp, rauhtd_pl, type);
 2594out:
 2595	kfree(rauhtd_pl);
 2596	return err;
 2597}
 2598
 2599static void mlxsw_sp_router_neighs_update_nh(struct mlxsw_sp *mlxsw_sp)
 2600{
 2601	struct mlxsw_sp_neigh_entry *neigh_entry;
 2602
 2603	mutex_lock(&mlxsw_sp->router->lock);
 2604	list_for_each_entry(neigh_entry, &mlxsw_sp->router->nexthop_neighs_list,
 2605			    nexthop_neighs_list_node)
 2606		/* If this neigh have nexthops, make the kernel think this neigh
 2607		 * is active regardless of the traffic.
 2608		 */
 2609		neigh_event_send(neigh_entry->key.n, NULL);
 2610	mutex_unlock(&mlxsw_sp->router->lock);
 2611}
 2612
 2613static void
 2614mlxsw_sp_router_neighs_update_work_schedule(struct mlxsw_sp *mlxsw_sp)
 2615{
 2616	unsigned long interval = mlxsw_sp->router->neighs_update.interval;
 2617
 2618	mlxsw_core_schedule_dw(&mlxsw_sp->router->neighs_update.dw,
 2619			       msecs_to_jiffies(interval));
 2620}
 2621
 2622static void mlxsw_sp_router_neighs_update_work(struct work_struct *work)
 2623{
 2624	struct mlxsw_sp_router *router;
 2625	int err;
 2626
 2627	router = container_of(work, struct mlxsw_sp_router,
 2628			      neighs_update.dw.work);
 2629	err = mlxsw_sp_router_neighs_update_rauhtd(router->mlxsw_sp);
 2630	if (err)
 2631		dev_err(router->mlxsw_sp->bus_info->dev, "Could not update kernel for neigh activity");
 2632
 2633	mlxsw_sp_router_neighs_update_nh(router->mlxsw_sp);
 2634
 2635	mlxsw_sp_router_neighs_update_work_schedule(router->mlxsw_sp);
 2636}
 2637
 2638static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct *work)
 2639{
 2640	struct mlxsw_sp_neigh_entry *neigh_entry;
 2641	struct mlxsw_sp_router *router;
 2642
 2643	router = container_of(work, struct mlxsw_sp_router,
 2644			      nexthop_probe_dw.work);
 2645	/* Iterate over nexthop neighbours, find those who are unresolved and
 2646	 * send arp on them. This solves the chicken-egg problem when
 2647	 * the nexthop wouldn't get offloaded until the neighbor is resolved
 2648	 * but it wouldn't get resolved ever in case traffic is flowing in HW
 2649	 * using different nexthop.
 2650	 */
 2651	mutex_lock(&router->lock);
 2652	list_for_each_entry(neigh_entry, &router->nexthop_neighs_list,
 2653			    nexthop_neighs_list_node)
 2654		if (!neigh_entry->connected)
 2655			neigh_event_send(neigh_entry->key.n, NULL);
 2656	mutex_unlock(&router->lock);
 2657
 2658	mlxsw_core_schedule_dw(&router->nexthop_probe_dw,
 2659			       MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL);
 2660}
 2661
 2662static void
 2663mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
 2664			      struct mlxsw_sp_neigh_entry *neigh_entry,
 2665			      bool removing, bool dead);
 2666
 2667static enum mlxsw_reg_rauht_op mlxsw_sp_rauht_op(bool adding)
 2668{
 2669	return adding ? MLXSW_REG_RAUHT_OP_WRITE_ADD :
 2670			MLXSW_REG_RAUHT_OP_WRITE_DELETE;
 2671}
 2672
 2673static int
 2674mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp *mlxsw_sp,
 2675				struct mlxsw_sp_neigh_entry *neigh_entry,
 2676				enum mlxsw_reg_rauht_op op)
 2677{
 2678	struct neighbour *n = neigh_entry->key.n;
 2679	u32 dip = ntohl(*((__be32 *) n->primary_key));
 2680	char rauht_pl[MLXSW_REG_RAUHT_LEN];
 2681
 2682	mlxsw_reg_rauht_pack4(rauht_pl, op, neigh_entry->rif, neigh_entry->ha,
 2683			      dip);
 2684	if (neigh_entry->counter_valid)
 2685		mlxsw_reg_rauht_pack_counter(rauht_pl,
 2686					     neigh_entry->counter_index);
 2687	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
 2688}
 2689
 2690static int
 2691mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp *mlxsw_sp,
 2692				struct mlxsw_sp_neigh_entry *neigh_entry,
 2693				enum mlxsw_reg_rauht_op op)
 2694{
 2695	struct neighbour *n = neigh_entry->key.n;
 2696	char rauht_pl[MLXSW_REG_RAUHT_LEN];
 2697	const char *dip = n->primary_key;
 2698
 2699	mlxsw_reg_rauht_pack6(rauht_pl, op, neigh_entry->rif, neigh_entry->ha,
 2700			      dip);
 2701	if (neigh_entry->counter_valid)
 2702		mlxsw_reg_rauht_pack_counter(rauht_pl,
 2703					     neigh_entry->counter_index);
 2704	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
 2705}
 2706
 2707bool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry *neigh_entry)
 2708{
 2709	struct neighbour *n = neigh_entry->key.n;
 2710
 2711	/* Packets with a link-local destination address are trapped
 2712	 * after LPM lookup and never reach the neighbour table, so
 2713	 * there is no need to program such neighbours to the device.
 2714	 */
 2715	if (ipv6_addr_type((struct in6_addr *) &n->primary_key) &
 2716	    IPV6_ADDR_LINKLOCAL)
 2717		return true;
 2718	return false;
 2719}
 2720
 2721static void
 2722mlxsw_sp_neigh_entry_update(struct mlxsw_sp *mlxsw_sp,
 2723			    struct mlxsw_sp_neigh_entry *neigh_entry,
 2724			    bool adding)
 2725{
 2726	enum mlxsw_reg_rauht_op op = mlxsw_sp_rauht_op(adding);
 2727	int err;
 2728
 2729	if (!adding && !neigh_entry->connected)
 2730		return;
 2731	neigh_entry->connected = adding;
 2732	if (neigh_entry->key.n->tbl->family == AF_INET) {
 2733		err = mlxsw_sp_router_neigh_entry_op4(mlxsw_sp, neigh_entry,
 2734						      op);
 2735		if (err)
 2736			return;
 2737	} else if (neigh_entry->key.n->tbl->family == AF_INET6) {
 2738		if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
 2739			return;
 2740		err = mlxsw_sp_router_neigh_entry_op6(mlxsw_sp, neigh_entry,
 2741						      op);
 2742		if (err)
 2743			return;
 2744	} else {
 2745		WARN_ON_ONCE(1);
 2746		return;
 2747	}
 2748
 2749	if (adding)
 2750		neigh_entry->key.n->flags |= NTF_OFFLOADED;
 2751	else
 2752		neigh_entry->key.n->flags &= ~NTF_OFFLOADED;
 2753}
 2754
 2755void
 2756mlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp *mlxsw_sp,
 2757				    struct mlxsw_sp_neigh_entry *neigh_entry,
 2758				    bool adding)
 2759{
 2760	if (adding)
 2761		mlxsw_sp_neigh_counter_alloc(mlxsw_sp, neigh_entry);
 2762	else
 2763		mlxsw_sp_neigh_counter_free(mlxsw_sp, neigh_entry);
 2764	mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, true);
 2765}
 2766
 2767struct mlxsw_sp_netevent_work {
 2768	struct work_struct work;
 2769	struct mlxsw_sp *mlxsw_sp;
 2770	struct neighbour *n;
 2771};
 2772
 2773static void mlxsw_sp_router_neigh_event_work(struct work_struct *work)
 2774{
 2775	struct mlxsw_sp_netevent_work *net_work =
 2776		container_of(work, struct mlxsw_sp_netevent_work, work);
 2777	struct mlxsw_sp *mlxsw_sp = net_work->mlxsw_sp;
 2778	struct mlxsw_sp_neigh_entry *neigh_entry;
 2779	struct neighbour *n = net_work->n;
 2780	unsigned char ha[ETH_ALEN];
 2781	bool entry_connected;
 2782	u8 nud_state, dead;
 2783
 2784	/* If these parameters are changed after we release the lock,
 2785	 * then we are guaranteed to receive another event letting us
 2786	 * know about it.
 2787	 */
 2788	read_lock_bh(&n->lock);
 2789	memcpy(ha, n->ha, ETH_ALEN);
 2790	nud_state = n->nud_state;
 2791	dead = n->dead;
 2792	read_unlock_bh(&n->lock);
 2793
 2794	mutex_lock(&mlxsw_sp->router->lock);
 2795	mlxsw_sp_span_respin(mlxsw_sp);
 2796
 2797	entry_connected = nud_state & NUD_VALID && !dead;
 2798	neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
 2799	if (!entry_connected && !neigh_entry)
 2800		goto out;
 2801	if (!neigh_entry) {
 2802		neigh_entry = mlxsw_sp_neigh_entry_create(mlxsw_sp, n);
 2803		if (IS_ERR(neigh_entry))
 2804			goto out;
 2805	}
 2806
 2807	if (neigh_entry->connected && entry_connected &&
 2808	    !memcmp(neigh_entry->ha, ha, ETH_ALEN))
 2809		goto out;
 2810
 2811	memcpy(neigh_entry->ha, ha, ETH_ALEN);
 2812	mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, entry_connected);
 2813	mlxsw_sp_nexthop_neigh_update(mlxsw_sp, neigh_entry, !entry_connected,
 2814				      dead);
 2815
 2816	if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
 2817		mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
 2818
 2819out:
 2820	mutex_unlock(&mlxsw_sp->router->lock);
 2821	neigh_release(n);
 2822	kfree(net_work);
 2823}
 2824
 2825static int mlxsw_sp_mp_hash_init(struct mlxsw_sp *mlxsw_sp);
 2826
 2827static void mlxsw_sp_router_mp_hash_event_work(struct work_struct *work)
 2828{
 2829	struct mlxsw_sp_netevent_work *net_work =
 2830		container_of(work, struct mlxsw_sp_netevent_work, work);
 2831	struct mlxsw_sp *mlxsw_sp = net_work->mlxsw_sp;
 2832
 2833	mlxsw_sp_mp_hash_init(mlxsw_sp);
 2834	kfree(net_work);
 2835}
 2836
 2837static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp);
 2838
 2839static void mlxsw_sp_router_update_priority_work(struct work_struct *work)
 2840{
 2841	struct mlxsw_sp_netevent_work *net_work =
 2842		container_of(work, struct mlxsw_sp_netevent_work, work);
 2843	struct mlxsw_sp *mlxsw_sp = net_work->mlxsw_sp;
 2844
 2845	__mlxsw_sp_router_init(mlxsw_sp);
 2846	kfree(net_work);
 2847}
 2848
 2849static int mlxsw_sp_router_schedule_work(struct net *net,
 2850					 struct mlxsw_sp_router *router,
 2851					 struct neighbour *n,
 2852					 void (*cb)(struct work_struct *))
 2853{
 2854	struct mlxsw_sp_netevent_work *net_work;
 2855
 2856	if (!net_eq(net, mlxsw_sp_net(router->mlxsw_sp)))
 2857		return NOTIFY_DONE;
 2858
 2859	net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
 2860	if (!net_work)
 2861		return NOTIFY_BAD;
 2862
 2863	/* Take a reference to ensure the neighbour won't be destructed until
 2864	 * we drop the reference in the work item.
 2865	 */
 2866	neigh_clone(n);
 2867
 2868	INIT_WORK(&net_work->work, cb);
 2869	net_work->mlxsw_sp = router->mlxsw_sp;
 2870	net_work->n = n;
 2871	mlxsw_core_schedule_work(&net_work->work);
 2872	return NOTIFY_DONE;
 2873}
 2874
 2875static bool mlxsw_sp_dev_lower_is_port(struct net_device *dev)
 2876{
 2877	struct mlxsw_sp_port *mlxsw_sp_port;
 2878
 2879	rcu_read_lock();
 2880	mlxsw_sp_port = mlxsw_sp_port_dev_lower_find_rcu(dev);
 2881	rcu_read_unlock();
 2882	return !!mlxsw_sp_port;
 2883}
 2884
 2885static int mlxsw_sp_router_schedule_neigh_work(struct mlxsw_sp_router *router,
 2886					       struct neighbour *n)
 2887{
 2888	struct net *net;
 2889
 2890	net = neigh_parms_net(n->parms);
 2891	return mlxsw_sp_router_schedule_work(net, router, n,
 2892					     mlxsw_sp_router_neigh_event_work);
 2893}
 2894
 2895static int mlxsw_sp_router_netevent_event(struct notifier_block *nb,
 2896					  unsigned long event, void *ptr)
 2897{
 2898	struct mlxsw_sp_router *router;
 2899	unsigned long interval;
 2900	struct neigh_parms *p;
 2901	struct neighbour *n;
 2902
 2903	router = container_of(nb, struct mlxsw_sp_router, netevent_nb);
 2904
 2905	switch (event) {
 2906	case NETEVENT_DELAY_PROBE_TIME_UPDATE:
 2907		p = ptr;
 2908
 2909		/* We don't care about changes in the default table. */
 2910		if (!p->dev || (p->tbl->family != AF_INET &&
 2911				p->tbl->family != AF_INET6))
 2912			return NOTIFY_DONE;
 2913
 2914		/* We are in atomic context and can't take RTNL mutex,
 2915		 * so use RCU variant to walk the device chain.
 2916		 */
 2917		if (!mlxsw_sp_dev_lower_is_port(p->dev))
 2918			return NOTIFY_DONE;
 2919
 2920		interval = jiffies_to_msecs(NEIGH_VAR(p, DELAY_PROBE_TIME));
 2921		router->neighs_update.interval = interval;
 2922		break;
 2923	case NETEVENT_NEIGH_UPDATE:
 2924		n = ptr;
 2925
 2926		if (n->tbl->family != AF_INET && n->tbl->family != AF_INET6)
 2927			return NOTIFY_DONE;
 2928
 2929		if (!mlxsw_sp_dev_lower_is_port(n->dev))
 2930			return NOTIFY_DONE;
 2931
 2932		return mlxsw_sp_router_schedule_neigh_work(router, n);
 2933
 2934	case NETEVENT_IPV4_MPATH_HASH_UPDATE:
 2935	case NETEVENT_IPV6_MPATH_HASH_UPDATE:
 2936		return mlxsw_sp_router_schedule_work(ptr, router, NULL,
 2937				mlxsw_sp_router_mp_hash_event_work);
 2938
 2939	case NETEVENT_IPV4_FWD_UPDATE_PRIORITY_UPDATE:
 2940		return mlxsw_sp_router_schedule_work(ptr, router, NULL,
 2941				mlxsw_sp_router_update_priority_work);
 2942	}
 2943
 2944	return NOTIFY_DONE;
 2945}
 2946
 2947static int mlxsw_sp_neigh_init(struct mlxsw_sp *mlxsw_sp)
 2948{
 2949	int err;
 2950
 2951	err = rhashtable_init(&mlxsw_sp->router->neigh_ht,
 2952			      &mlxsw_sp_neigh_ht_params);
 2953	if (err)
 2954		return err;
 2955
 2956	/* Initialize the polling interval according to the default
 2957	 * table.
 2958	 */
 2959	mlxsw_sp_router_neighs_update_interval_init(mlxsw_sp);
 2960
 2961	/* Create the delayed works for the activity_update */
 2962	INIT_DELAYED_WORK(&mlxsw_sp->router->neighs_update.dw,
 2963			  mlxsw_sp_router_neighs_update_work);
 2964	INIT_DELAYED_WORK(&mlxsw_sp->router->nexthop_probe_dw,
 2965			  mlxsw_sp_router_probe_unresolved_nexthops);
 2966	atomic_set(&mlxsw_sp->router->neighs_update.neigh_count, 0);
 2967	mlxsw_core_schedule_dw(&mlxsw_sp->router->neighs_update.dw, 0);
 2968	mlxsw_core_schedule_dw(&mlxsw_sp->router->nexthop_probe_dw, 0);
 2969	return 0;
 2970}
 2971
 2972static void mlxsw_sp_neigh_fini(struct mlxsw_sp *mlxsw_sp)
 2973{
 2974	cancel_delayed_work_sync(&mlxsw_sp->router->neighs_update.dw);
 2975	cancel_delayed_work_sync(&mlxsw_sp->router->nexthop_probe_dw);
 2976	rhashtable_destroy(&mlxsw_sp->router->neigh_ht);
 2977}
 2978
 2979static void mlxsw_sp_neigh_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
 2980					 struct mlxsw_sp_rif *rif)
 2981{
 2982	struct mlxsw_sp_neigh_entry *neigh_entry, *tmp;
 2983
 2984	list_for_each_entry_safe(neigh_entry, tmp, &rif->neigh_list,
 2985				 rif_list_node) {
 2986		mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, false);
 2987		mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
 2988	}
 2989}
 2990
 2991struct mlxsw_sp_neigh_rif_made_sync {
 2992	struct mlxsw_sp *mlxsw_sp;
 2993	struct mlxsw_sp_rif *rif;
 2994	int err;
 2995};
 2996
 2997static void mlxsw_sp_neigh_rif_made_sync_each(struct neighbour *n, void *data)
 2998{
 2999	struct mlxsw_sp_neigh_rif_made_sync *rms = data;
 3000	int rc;
 3001
 3002	if (rms->err)
 3003		return;
 3004	if (n->dev != mlxsw_sp_rif_dev(rms->rif))
 3005		return;
 3006	rc = mlxsw_sp_router_schedule_neigh_work(rms->mlxsw_sp->router, n);
 3007	if (rc != NOTIFY_DONE)
 3008		rms->err = -ENOMEM;
 3009}
 3010
 3011static int mlxsw_sp_neigh_rif_made_sync(struct mlxsw_sp *mlxsw_sp,
 3012					struct mlxsw_sp_rif *rif)
 3013{
 3014	struct mlxsw_sp_neigh_rif_made_sync rms = {
 3015		.mlxsw_sp = mlxsw_sp,
 3016		.rif = rif,
 3017	};
 3018
 3019	if (!mlxsw_sp_dev_lower_is_port(mlxsw_sp_rif_dev(rif)))
 3020		return 0;
 3021
 3022	neigh_for_each(&arp_tbl, mlxsw_sp_neigh_rif_made_sync_each, &rms);
 3023	if (rms.err)
 3024		goto err_arp;
 3025
 3026#if IS_ENABLED(CONFIG_IPV6)
 3027	neigh_for_each(&nd_tbl, mlxsw_sp_neigh_rif_made_sync_each, &rms);
 3028#endif
 3029	if (rms.err)
 3030		goto err_nd;
 3031
 3032	return 0;
 3033
 3034err_nd:
 3035err_arp:
 3036	mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif);
 3037	return rms.err;
 3038}
 3039
 3040enum mlxsw_sp_nexthop_type {
 3041	MLXSW_SP_NEXTHOP_TYPE_ETH,
 3042	MLXSW_SP_NEXTHOP_TYPE_IPIP,
 3043};
 3044
 3045enum mlxsw_sp_nexthop_action {
 3046	/* Nexthop forwards packets to an egress RIF */
 3047	MLXSW_SP_NEXTHOP_ACTION_FORWARD,
 3048	/* Nexthop discards packets */
 3049	MLXSW_SP_NEXTHOP_ACTION_DISCARD,
 3050	/* Nexthop traps packets */
 3051	MLXSW_SP_NEXTHOP_ACTION_TRAP,
 3052};
 3053
 3054struct mlxsw_sp_nexthop_key {
 3055	struct fib_nh *fib_nh;
 3056};
 3057
 3058struct mlxsw_sp_nexthop_counter;
 3059
 3060struct mlxsw_sp_nexthop {
 3061	struct list_head neigh_list_node; /* member of neigh entry list */
 3062	struct list_head crif_list_node;
 3063	struct list_head router_list_node;
 3064	struct mlxsw_sp_nexthop_group_info *nhgi; /* pointer back to the group
 3065						   * this nexthop belongs to
 3066						   */
 3067	struct rhash_head ht_node;
 3068	struct neigh_table *neigh_tbl;
 3069	struct mlxsw_sp_nexthop_key key;
 3070	unsigned char gw_addr[sizeof(struct in6_addr)];
 3071	int ifindex;
 3072	int nh_weight;
 3073	int norm_nh_weight;
 3074	int num_adj_entries;
 3075	struct mlxsw_sp_crif *crif;
 3076	u8 should_offload:1, /* set indicates this nexthop should be written
 3077			      * to the adjacency table.
 3078			      */
 3079	   offloaded:1, /* set indicates this nexthop was written to the
 3080			 * adjacency table.
 3081			 */
 3082	   update:1; /* set indicates this nexthop should be updated in the
 3083		      * adjacency table (f.e., its MAC changed).
 3084		      */
 3085	enum mlxsw_sp_nexthop_action action;
 3086	enum mlxsw_sp_nexthop_type type;
 3087	union {
 3088		struct mlxsw_sp_neigh_entry *neigh_entry;
 3089		struct mlxsw_sp_ipip_entry *ipip_entry;
 3090	};
 3091	struct mlxsw_sp_nexthop_counter *counter;
 3092	u32 id;		/* NH ID for members of a NH object group. */
 3093};
 3094
 3095static struct net_device *
 3096mlxsw_sp_nexthop_dev(const struct mlxsw_sp_nexthop *nh)
 3097{
 3098	if (!nh->crif)
 3099		return NULL;
 3100	return nh->crif->key.dev;
 3101}
 3102
 3103enum mlxsw_sp_nexthop_group_type {
 3104	MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4,
 3105	MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6,
 3106	MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ,
 3107};
 3108
 3109struct mlxsw_sp_nexthop_group_info {
 3110	struct mlxsw_sp_nexthop_group *nh_grp;
 3111	u32 adj_index;
 3112	u16 ecmp_size;
 3113	u16 count;
 3114	int sum_norm_weight;
 3115	u8 adj_index_valid:1,
 3116	   gateway:1, /* routes using the group use a gateway */
 3117	   is_resilient:1,
 3118	   hw_stats:1;
 3119	struct list_head list; /* member in nh_res_grp_list */
 3120	struct xarray nexthop_counters;
 3121	struct mlxsw_sp_nexthop nexthops[] __counted_by(count);
 3122};
 3123
 3124static struct mlxsw_sp_rif *
 3125mlxsw_sp_nhgi_rif(const struct mlxsw_sp_nexthop_group_info *nhgi)
 3126{
 3127	struct mlxsw_sp_crif *crif = nhgi->nexthops[0].crif;
 3128
 3129	if (!crif)
 3130		return NULL;
 3131	return crif->rif;
 3132}
 3133
 3134struct mlxsw_sp_nexthop_group_vr_key {
 3135	u16 vr_id;
 3136	enum mlxsw_sp_l3proto proto;
 3137};
 3138
 3139struct mlxsw_sp_nexthop_group_vr_entry {
 3140	struct list_head list; /* member in vr_list */
 3141	struct rhash_head ht_node; /* member in vr_ht */
 3142	refcount_t ref_count;
 3143	struct mlxsw_sp_nexthop_group_vr_key key;
 3144};
 3145
 3146struct mlxsw_sp_nexthop_group {
 3147	struct rhash_head ht_node;
 3148	struct list_head fib_list; /* list of fib entries that use this group */
 3149	union {
 3150		struct {
 3151			struct fib_info *fi;
 3152		} ipv4;
 3153		struct {
 3154			u32 id;
 3155		} obj;
 3156	};
 3157	struct mlxsw_sp_nexthop_group_info *nhgi;
 3158	struct list_head vr_list;
 3159	struct rhashtable vr_ht;
 3160	enum mlxsw_sp_nexthop_group_type type;
 3161	bool can_destroy;
 3162};
 3163
 3164struct mlxsw_sp_nexthop_counter {
 3165	unsigned int counter_index;
 3166	refcount_t ref_count;
 3167};
 3168
 3169static struct mlxsw_sp_nexthop_counter *
 3170mlxsw_sp_nexthop_counter_alloc(struct mlxsw_sp *mlxsw_sp)
 3171{
 3172	struct mlxsw_sp_nexthop_counter *nhct;
 3173	int err;
 3174
 3175	nhct = kzalloc(sizeof(*nhct), GFP_KERNEL);
 3176	if (!nhct)
 3177		return ERR_PTR(-ENOMEM);
 3178
 3179	err = mlxsw_sp_flow_counter_alloc(mlxsw_sp, &nhct->counter_index);
 3180	if (err)
 3181		goto err_counter_alloc;
 3182
 3183	refcount_set(&nhct->ref_count, 1);
 3184	return nhct;
 3185
 3186err_counter_alloc:
 3187	kfree(nhct);
 3188	return ERR_PTR(err);
 3189}
 3190
 3191static void
 3192mlxsw_sp_nexthop_counter_free(struct mlxsw_sp *mlxsw_sp,
 3193			      struct mlxsw_sp_nexthop_counter *nhct)
 3194{
 3195	mlxsw_sp_flow_counter_free(mlxsw_sp, nhct->counter_index);
 3196	kfree(nhct);
 3197}
 3198
 3199static struct mlxsw_sp_nexthop_counter *
 3200mlxsw_sp_nexthop_sh_counter_get(struct mlxsw_sp *mlxsw_sp,
 3201				struct mlxsw_sp_nexthop *nh)
 3202{
 3203	struct mlxsw_sp_nexthop_group *nh_grp = nh->nhgi->nh_grp;
 3204	struct mlxsw_sp_nexthop_counter *nhct;
 3205	int err;
 3206
 3207	nhct = xa_load(&nh_grp->nhgi->nexthop_counters, nh->id);
 3208	if (nhct) {
 3209		refcount_inc(&nhct->ref_count);
 3210		return nhct;
 3211	}
 3212
 3213	nhct = mlxsw_sp_nexthop_counter_alloc(mlxsw_sp);
 3214	if (IS_ERR(nhct))
 3215		return nhct;
 3216
 3217	err = xa_err(xa_store(&nh_grp->nhgi->nexthop_counters, nh->id, nhct,
 3218			      GFP_KERNEL));
 3219	if (err)
 3220		goto err_store;
 3221
 3222	return nhct;
 3223
 3224err_store:
 3225	mlxsw_sp_nexthop_counter_free(mlxsw_sp, nhct);
 3226	return ERR_PTR(err);
 3227}
 3228
 3229static void mlxsw_sp_nexthop_sh_counter_put(struct mlxsw_sp *mlxsw_sp,
 3230					    struct mlxsw_sp_nexthop *nh)
 3231{
 3232	struct mlxsw_sp_nexthop_group *nh_grp = nh->nhgi->nh_grp;
 3233	struct mlxsw_sp_nexthop_counter *nhct;
 3234
 3235	nhct = xa_load(&nh_grp->nhgi->nexthop_counters, nh->id);
 3236	if (WARN_ON(!nhct))
 3237		return;
 3238
 3239	if (!refcount_dec_and_test(&nhct->ref_count))
 3240		return;
 3241
 3242	xa_erase(&nh_grp->nhgi->nexthop_counters, nh->id);
 3243	mlxsw_sp_nexthop_counter_free(mlxsw_sp, nhct);
 3244}
 3245
 3246int mlxsw_sp_nexthop_counter_enable(struct mlxsw_sp *mlxsw_sp,
 3247				    struct mlxsw_sp_nexthop *nh)
 3248{
 3249	const char *table_adj = MLXSW_SP_DPIPE_TABLE_NAME_ADJ;
 3250	struct mlxsw_sp_nexthop_counter *nhct;
 3251	struct devlink *devlink;
 3252	bool dpipe_stats;
 3253
 3254	if (nh->counter)
 3255		return 0;
 3256
 3257	devlink = priv_to_devlink(mlxsw_sp->core);
 3258	dpipe_stats = devlink_dpipe_table_counter_enabled(devlink, table_adj);
 3259	if (!(nh->nhgi->hw_stats || dpipe_stats))
 3260		return 0;
 3261
 3262	if (nh->id)
 3263		nhct = mlxsw_sp_nexthop_sh_counter_get(mlxsw_sp, nh);
 3264	else
 3265		nhct = mlxsw_sp_nexthop_counter_alloc(mlxsw_sp);
 3266	if (IS_ERR(nhct))
 3267		return PTR_ERR(nhct);
 3268
 3269	nh->counter = nhct;
 3270	return 0;
 3271}
 3272
 3273void mlxsw_sp_nexthop_counter_disable(struct mlxsw_sp *mlxsw_sp,
 3274				      struct mlxsw_sp_nexthop *nh)
 3275{
 3276	if (!nh->counter)
 3277		return;
 3278
 3279	if (nh->id)
 3280		mlxsw_sp_nexthop_sh_counter_put(mlxsw_sp, nh);
 3281	else
 3282		mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh->counter);
 3283	nh->counter = NULL;
 3284}
 3285
 3286static int mlxsw_sp_nexthop_counter_update(struct mlxsw_sp *mlxsw_sp,
 3287					   struct mlxsw_sp_nexthop *nh)
 3288{
 3289	if (nh->nhgi->hw_stats)
 3290		return mlxsw_sp_nexthop_counter_enable(mlxsw_sp, nh);
 3291	mlxsw_sp_nexthop_counter_disable(mlxsw_sp, nh);
 3292	return 0;
 3293}
 3294
 3295int mlxsw_sp_nexthop_counter_get(struct mlxsw_sp *mlxsw_sp,
 3296				 struct mlxsw_sp_nexthop *nh, u64 *p_counter)
 3297{
 3298	if (!nh->counter)
 3299		return -EINVAL;
 3300
 3301	return mlxsw_sp_flow_counter_get(mlxsw_sp, nh->counter->counter_index,
 3302					 true, p_counter, NULL);
 3303}
 3304
 3305struct mlxsw_sp_nexthop *mlxsw_sp_nexthop_next(struct mlxsw_sp_router *router,
 3306					       struct mlxsw_sp_nexthop *nh)
 3307{
 3308	if (!nh) {
 3309		if (list_empty(&router->nexthop_list))
 3310			return NULL;
 3311		else
 3312			return list_first_entry(&router->nexthop_list,
 3313						typeof(*nh), router_list_node);
 3314	}
 3315	if (list_is_last(&nh->router_list_node, &router->nexthop_list))
 3316		return NULL;
 3317	return list_next_entry(nh, router_list_node);
 3318}
 3319
 3320bool mlxsw_sp_nexthop_is_forward(const struct mlxsw_sp_nexthop *nh)
 3321{
 3322	return nh->offloaded && nh->action == MLXSW_SP_NEXTHOP_ACTION_FORWARD;
 3323}
 3324
 3325unsigned char *mlxsw_sp_nexthop_ha(struct mlxsw_sp_nexthop *nh)
 3326{
 3327	if (nh->type != MLXSW_SP_NEXTHOP_TYPE_ETH ||
 3328	    !mlxsw_sp_nexthop_is_forward(nh))
 3329		return NULL;
 3330	return nh->neigh_entry->ha;
 3331}
 3332
 3333int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop *nh, u32 *p_adj_index,
 3334			     u32 *p_adj_size, u32 *p_adj_hash_index)
 3335{
 3336	struct mlxsw_sp_nexthop_group_info *nhgi = nh->nhgi;
 3337	u32 adj_hash_index = 0;
 3338	int i;
 3339
 3340	if (!nh->offloaded || !nhgi->adj_index_valid)
 3341		return -EINVAL;
 3342
 3343	*p_adj_index = nhgi->adj_index;
 3344	*p_adj_size = nhgi->ecmp_size;
 3345
 3346	for (i = 0; i < nhgi->count; i++) {
 3347		struct mlxsw_sp_nexthop *nh_iter = &nhgi->nexthops[i];
 3348
 3349		if (nh_iter == nh)
 3350			break;
 3351		if (nh_iter->offloaded)
 3352			adj_hash_index += nh_iter->num_adj_entries;
 3353	}
 3354
 3355	*p_adj_hash_index = adj_hash_index;
 3356	return 0;
 3357}
 3358
 3359struct mlxsw_sp_rif *mlxsw_sp_nexthop_rif(struct mlxsw_sp_nexthop *nh)
 3360{
 3361	if (WARN_ON(!nh->crif))
 3362		return NULL;
 3363	return nh->crif->rif;
 3364}
 3365
 3366bool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop *nh)
 3367{
 3368	struct mlxsw_sp_nexthop_group_info *nhgi = nh->nhgi;
 3369	int i;
 3370
 3371	for (i = 0; i < nhgi->count; i++) {
 3372		struct mlxsw_sp_nexthop *nh_iter = &nhgi->nexthops[i];
 3373
 3374		if (nh_iter->type == MLXSW_SP_NEXTHOP_TYPE_IPIP)
 3375			return true;
 3376	}
 3377	return false;
 3378}
 3379
 3380static const struct rhashtable_params mlxsw_sp_nexthop_group_vr_ht_params = {
 3381	.key_offset = offsetof(struct mlxsw_sp_nexthop_group_vr_entry, key),
 3382	.head_offset = offsetof(struct mlxsw_sp_nexthop_group_vr_entry, ht_node),
 3383	.key_len = sizeof(struct mlxsw_sp_nexthop_group_vr_key),
 3384	.automatic_shrinking = true,
 3385};
 3386
 3387static struct mlxsw_sp_nexthop_group_vr_entry *
 3388mlxsw_sp_nexthop_group_vr_entry_lookup(struct mlxsw_sp_nexthop_group *nh_grp,
 3389				       const struct mlxsw_sp_fib *fib)
 3390{
 3391	struct mlxsw_sp_nexthop_group_vr_key key;
 3392
 3393	memset(&key, 0, sizeof(key));
 3394	key.vr_id = fib->vr->id;
 3395	key.proto = fib->proto;
 3396	return rhashtable_lookup_fast(&nh_grp->vr_ht, &key,
 3397				      mlxsw_sp_nexthop_group_vr_ht_params);
 3398}
 3399
 3400static int
 3401mlxsw_sp_nexthop_group_vr_entry_create(struct mlxsw_sp_nexthop_group *nh_grp,
 3402				       const struct mlxsw_sp_fib *fib)
 3403{
 3404	struct mlxsw_sp_nexthop_group_vr_entry *vr_entry;
 3405	int err;
 3406
 3407	vr_entry = kzalloc(sizeof(*vr_entry), GFP_KERNEL);
 3408	if (!vr_entry)
 3409		return -ENOMEM;
 3410
 3411	vr_entry->key.vr_id = fib->vr->id;
 3412	vr_entry->key.proto = fib->proto;
 3413	refcount_set(&vr_entry->ref_count, 1);
 3414
 3415	err = rhashtable_insert_fast(&nh_grp->vr_ht, &vr_entry->ht_node,
 3416				     mlxsw_sp_nexthop_group_vr_ht_params);
 3417	if (err)
 3418		goto err_hashtable_insert;
 3419
 3420	list_add(&vr_entry->list, &nh_grp->vr_list);
 3421
 3422	return 0;
 3423
 3424err_hashtable_insert:
 3425	kfree(vr_entry);
 3426	return err;
 3427}
 3428
 3429static void
 3430mlxsw_sp_nexthop_group_vr_entry_destroy(struct mlxsw_sp_nexthop_group *nh_grp,
 3431					struct mlxsw_sp_nexthop_group_vr_entry *vr_entry)
 3432{
 3433	list_del(&vr_entry->list);
 3434	rhashtable_remove_fast(&nh_grp->vr_ht, &vr_entry->ht_node,
 3435			       mlxsw_sp_nexthop_group_vr_ht_params);
 3436	kfree(vr_entry);
 3437}
 3438
 3439static int
 3440mlxsw_sp_nexthop_group_vr_link(struct mlxsw_sp_nexthop_group *nh_grp,
 3441			       const struct mlxsw_sp_fib *fib)
 3442{
 3443	struct mlxsw_sp_nexthop_group_vr_entry *vr_entry;
 3444
 3445	vr_entry = mlxsw_sp_nexthop_group_vr_entry_lookup(nh_grp, fib);
 3446	if (vr_entry) {
 3447		refcount_inc(&vr_entry->ref_count);
 3448		return 0;
 3449	}
 3450
 3451	return mlxsw_sp_nexthop_group_vr_entry_create(nh_grp, fib);
 3452}
 3453
 3454static void
 3455mlxsw_sp_nexthop_group_vr_unlink(struct mlxsw_sp_nexthop_group *nh_grp,
 3456				 const struct mlxsw_sp_fib *fib)
 3457{
 3458	struct mlxsw_sp_nexthop_group_vr_entry *vr_entry;
 3459
 3460	vr_entry = mlxsw_sp_nexthop_group_vr_entry_lookup(nh_grp, fib);
 3461	if (WARN_ON_ONCE(!vr_entry))
 3462		return;
 3463
 3464	if (!refcount_dec_and_test(&vr_entry->ref_count))
 3465		return;
 3466
 3467	mlxsw_sp_nexthop_group_vr_entry_destroy(nh_grp, vr_entry);
 3468}
 3469
 3470struct mlxsw_sp_nexthop_group_cmp_arg {
 3471	enum mlxsw_sp_nexthop_group_type type;
 3472	union {
 3473		struct fib_info *fi;
 3474		struct mlxsw_sp_fib6_entry *fib6_entry;
 3475		u32 id;
 3476	};
 3477};
 3478
 3479static bool
 3480mlxsw_sp_nexthop6_group_has_nexthop(const struct mlxsw_sp_nexthop_group *nh_grp,
 3481				    const struct in6_addr *gw, int ifindex,
 3482				    int weight)
 3483{
 3484	int i;
 3485
 3486	for (i = 0; i < nh_grp->nhgi->count; i++) {
 3487		const struct mlxsw_sp_nexthop *nh;
 3488
 3489		nh = &nh_grp->nhgi->nexthops[i];
 3490		if (nh->ifindex == ifindex && nh->nh_weight == weight &&
 3491		    ipv6_addr_equal(gw, (struct in6_addr *) nh->gw_addr))
 3492			return true;
 3493	}
 3494
 3495	return false;
 3496}
 3497
 3498static bool
 3499mlxsw_sp_nexthop6_group_cmp(const struct mlxsw_sp_nexthop_group *nh_grp,
 3500			    const struct mlxsw_sp_fib6_entry *fib6_entry)
 3501{
 3502	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
 3503
 3504	if (nh_grp->nhgi->count != fib6_entry->nrt6)
 3505		return false;
 3506
 3507	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
 3508		struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
 3509		struct in6_addr *gw;
 3510		int ifindex, weight;
 3511
 3512		ifindex = fib6_nh->fib_nh_dev->ifindex;
 3513		weight = fib6_nh->fib_nh_weight;
 3514		gw = &fib6_nh->fib_nh_gw6;
 3515		if (!mlxsw_sp_nexthop6_group_has_nexthop(nh_grp, gw, ifindex,
 3516							 weight))
 3517			return false;
 3518	}
 3519
 3520	return true;
 3521}
 3522
 3523static int
 3524mlxsw_sp_nexthop_group_cmp(struct rhashtable_compare_arg *arg, const void *ptr)
 3525{
 3526	const struct mlxsw_sp_nexthop_group_cmp_arg *cmp_arg = arg->key;
 3527	const struct mlxsw_sp_nexthop_group *nh_grp = ptr;
 3528
 3529	if (nh_grp->type != cmp_arg->type)
 3530		return 1;
 3531
 3532	switch (cmp_arg->type) {
 3533	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4:
 3534		return cmp_arg->fi != nh_grp->ipv4.fi;
 3535	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6:
 3536		return !mlxsw_sp_nexthop6_group_cmp(nh_grp,
 3537						    cmp_arg->fib6_entry);
 3538	case MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ:
 3539		return cmp_arg->id != nh_grp->obj.id;
 3540	default:
 3541		WARN_ON(1);
 3542		return 1;
 3543	}
 3544}
 3545
 3546static u32 mlxsw_sp_nexthop_group_hash_obj(const void *data, u32 len, u32 seed)
 3547{
 3548	const struct mlxsw_sp_nexthop_group *nh_grp = data;
 3549	const struct mlxsw_sp_nexthop *nh;
 3550	struct fib_info *fi;
 3551	unsigned int val;
 3552	int i;
 3553
 3554	switch (nh_grp->type) {
 3555	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4:
 3556		fi = nh_grp->ipv4.fi;
 3557		return jhash(&fi, sizeof(fi), seed);
 3558	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6:
 3559		val = nh_grp->nhgi->count;
 3560		for (i = 0; i < nh_grp->nhgi->count; i++) {
 3561			nh = &nh_grp->nhgi->nexthops[i];
 3562			val ^= jhash(&nh->ifindex, sizeof(nh->ifindex), seed);
 3563			val ^= jhash(&nh->gw_addr, sizeof(nh->gw_addr), seed);
 3564		}
 3565		return jhash(&val, sizeof(val), seed);
 3566	case MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ:
 3567		return jhash(&nh_grp->obj.id, sizeof(nh_grp->obj.id), seed);
 3568	default:
 3569		WARN_ON(1);
 3570		return 0;
 3571	}
 3572}
 3573
 3574static u32
 3575mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry *fib6_entry, u32 seed)
 3576{
 3577	unsigned int val = fib6_entry->nrt6;
 3578	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
 3579
 3580	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
 3581		struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
 3582		struct net_device *dev = fib6_nh->fib_nh_dev;
 3583		struct in6_addr *gw = &fib6_nh->fib_nh_gw6;
 3584
 3585		val ^= jhash(&dev->ifindex, sizeof(dev->ifindex), seed);
 3586		val ^= jhash(gw, sizeof(*gw), seed);
 3587	}
 3588
 3589	return jhash(&val, sizeof(val), seed);
 3590}
 3591
 3592static u32
 3593mlxsw_sp_nexthop_group_hash(const void *data, u32 len, u32 seed)
 3594{
 3595	const struct mlxsw_sp_nexthop_group_cmp_arg *cmp_arg = data;
 3596
 3597	switch (cmp_arg->type) {
 3598	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4:
 3599		return jhash(&cmp_arg->fi, sizeof(cmp_arg->fi), seed);
 3600	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6:
 3601		return mlxsw_sp_nexthop6_group_hash(cmp_arg->fib6_entry, seed);
 3602	case MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ:
 3603		return jhash(&cmp_arg->id, sizeof(cmp_arg->id), seed);
 3604	default:
 3605		WARN_ON(1);
 3606		return 0;
 3607	}
 3608}
 3609
 3610static const struct rhashtable_params mlxsw_sp_nexthop_group_ht_params = {
 3611	.head_offset = offsetof(struct mlxsw_sp_nexthop_group, ht_node),
 3612	.hashfn	     = mlxsw_sp_nexthop_group_hash,
 3613	.obj_hashfn  = mlxsw_sp_nexthop_group_hash_obj,
 3614	.obj_cmpfn   = mlxsw_sp_nexthop_group_cmp,
 3615};
 3616
 3617static int mlxsw_sp_nexthop_group_insert(struct mlxsw_sp *mlxsw_sp,
 3618					 struct mlxsw_sp_nexthop_group *nh_grp)
 3619{
 3620	if (nh_grp->type == MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6 &&
 3621	    !nh_grp->nhgi->gateway)
 3622		return 0;
 3623
 3624	return rhashtable_insert_fast(&mlxsw_sp->router->nexthop_group_ht,
 3625				      &nh_grp->ht_node,
 3626				      mlxsw_sp_nexthop_group_ht_params);
 3627}
 3628
 3629static void mlxsw_sp_nexthop_group_remove(struct mlxsw_sp *mlxsw_sp,
 3630					  struct mlxsw_sp_nexthop_group *nh_grp)
 3631{
 3632	if (nh_grp->type == MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6 &&
 3633	    !nh_grp->nhgi->gateway)
 3634		return;
 3635
 3636	rhashtable_remove_fast(&mlxsw_sp->router->nexthop_group_ht,
 3637			       &nh_grp->ht_node,
 3638			       mlxsw_sp_nexthop_group_ht_params);
 3639}
 3640
 3641static struct mlxsw_sp_nexthop_group *
 3642mlxsw_sp_nexthop4_group_lookup(struct mlxsw_sp *mlxsw_sp,
 3643			       struct fib_info *fi)
 3644{
 3645	struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg;
 3646
 3647	cmp_arg.type = MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4;
 3648	cmp_arg.fi = fi;
 3649	return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_group_ht,
 3650				      &cmp_arg,
 3651				      mlxsw_sp_nexthop_group_ht_params);
 3652}
 3653
 3654static struct mlxsw_sp_nexthop_group *
 3655mlxsw_sp_nexthop6_group_lookup(struct mlxsw_sp *mlxsw_sp,
 3656			       struct mlxsw_sp_fib6_entry *fib6_entry)
 3657{
 3658	struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg;
 3659
 3660	cmp_arg.type = MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6;
 3661	cmp_arg.fib6_entry = fib6_entry;
 3662	return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_group_ht,
 3663				      &cmp_arg,
 3664				      mlxsw_sp_nexthop_group_ht_params);
 3665}
 3666
 3667static const struct rhashtable_params mlxsw_sp_nexthop_ht_params = {
 3668	.key_offset = offsetof(struct mlxsw_sp_nexthop, key),
 3669	.head_offset = offsetof(struct mlxsw_sp_nexthop, ht_node),
 3670	.key_len = sizeof(struct mlxsw_sp_nexthop_key),
 3671};
 3672
 3673static int mlxsw_sp_nexthop_insert(struct mlxsw_sp *mlxsw_sp,
 3674				   struct mlxsw_sp_nexthop *nh)
 3675{
 3676	return rhashtable_insert_fast(&mlxsw_sp->router->nexthop_ht,
 3677				      &nh->ht_node, mlxsw_sp_nexthop_ht_params);
 3678}
 3679
 3680static void mlxsw_sp_nexthop_remove(struct mlxsw_sp *mlxsw_sp,
 3681				    struct mlxsw_sp_nexthop *nh)
 3682{
 3683	rhashtable_remove_fast(&mlxsw_sp->router->nexthop_ht, &nh->ht_node,
 3684			       mlxsw_sp_nexthop_ht_params);
 3685}
 3686
 3687static struct mlxsw_sp_nexthop *
 3688mlxsw_sp_nexthop_lookup(struct mlxsw_sp *mlxsw_sp,
 3689			struct mlxsw_sp_nexthop_key key)
 3690{
 3691	return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_ht, &key,
 3692				      mlxsw_sp_nexthop_ht_params);
 3693}
 3694
 3695static int mlxsw_sp_adj_index_mass_update_vr(struct mlxsw_sp *mlxsw_sp,
 3696					     enum mlxsw_sp_l3proto proto,
 3697					     u16 vr_id,
 3698					     u32 adj_index, u16 ecmp_size,
 3699					     u32 new_adj_index,
 3700					     u16 new_ecmp_size)
 3701{
 3702	char raleu_pl[MLXSW_REG_RALEU_LEN];
 3703
 3704	mlxsw_reg_raleu_pack(raleu_pl,
 3705			     (enum mlxsw_reg_ralxx_protocol) proto, vr_id,
 3706			     adj_index, ecmp_size, new_adj_index,
 3707			     new_ecmp_size);
 3708	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raleu), raleu_pl);
 3709}
 3710
 3711static int mlxsw_sp_adj_index_mass_update(struct mlxsw_sp *mlxsw_sp,
 3712					  struct mlxsw_sp_nexthop_group *nh_grp,
 3713					  u32 old_adj_index, u16 old_ecmp_size)
 3714{
 3715	struct mlxsw_sp_nexthop_group_info *nhgi = nh_grp->nhgi;
 3716	struct mlxsw_sp_nexthop_group_vr_entry *vr_entry;
 3717	int err;
 3718
 3719	list_for_each_entry(vr_entry, &nh_grp->vr_list, list) {
 3720		err = mlxsw_sp_adj_index_mass_update_vr(mlxsw_sp,
 3721							vr_entry->key.proto,
 3722							vr_entry->key.vr_id,
 3723							old_adj_index,
 3724							old_ecmp_size,
 3725							nhgi->adj_index,
 3726							nhgi->ecmp_size);
 3727		if (err)
 3728			goto err_mass_update_vr;
 3729	}
 3730	return 0;
 3731
 3732err_mass_update_vr:
 3733	list_for_each_entry_continue_reverse(vr_entry, &nh_grp->vr_list, list)
 3734		mlxsw_sp_adj_index_mass_update_vr(mlxsw_sp, vr_entry->key.proto,
 3735						  vr_entry->key.vr_id,
 3736						  nhgi->adj_index,
 3737						  nhgi->ecmp_size,
 3738						  old_adj_index, old_ecmp_size);
 3739	return err;
 3740}
 3741
 3742static int __mlxsw_sp_nexthop_eth_update(struct mlxsw_sp *mlxsw_sp,
 3743					 u32 adj_index,
 3744					 struct mlxsw_sp_nexthop *nh,
 3745					 bool force, char *ratr_pl)
 3746{
 3747	struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
 3748	struct mlxsw_sp_rif *rif = mlxsw_sp_nexthop_rif(nh);
 3749	enum mlxsw_reg_ratr_op op;
 3750	u16 rif_index;
 3751
 3752	rif_index = rif ? rif->rif_index :
 3753			  mlxsw_sp->router->lb_crif->rif->rif_index;
 3754	op = force ? MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY :
 3755		     MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY_ON_ACTIVITY;
 3756	mlxsw_reg_ratr_pack(ratr_pl, op, true, MLXSW_REG_RATR_TYPE_ETHERNET,
 3757			    adj_index, rif_index);
 3758	switch (nh->action) {
 3759	case MLXSW_SP_NEXTHOP_ACTION_FORWARD:
 3760		mlxsw_reg_ratr_eth_entry_pack(ratr_pl, neigh_entry->ha);
 3761		break;
 3762	case MLXSW_SP_NEXTHOP_ACTION_DISCARD:
 3763		mlxsw_reg_ratr_trap_action_set(ratr_pl,
 3764					       MLXSW_REG_RATR_TRAP_ACTION_DISCARD_ERRORS);
 3765		break;
 3766	case MLXSW_SP_NEXTHOP_ACTION_TRAP:
 3767		mlxsw_reg_ratr_trap_action_set(ratr_pl,
 3768					       MLXSW_REG_RATR_TRAP_ACTION_TRAP);
 3769		mlxsw_reg_ratr_trap_id_set(ratr_pl, MLXSW_TRAP_ID_RTR_EGRESS0);
 3770		break;
 3771	default:
 3772		WARN_ON_ONCE(1);
 3773		return -EINVAL;
 3774	}
 3775	if (nh->counter)
 3776		mlxsw_reg_ratr_counter_pack(ratr_pl, nh->counter->counter_index,
 3777					    true);
 3778	else
 3779		mlxsw_reg_ratr_counter_pack(ratr_pl, 0, false);
 3780
 3781	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
 3782}
 3783
 3784int mlxsw_sp_nexthop_eth_update(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
 3785				struct mlxsw_sp_nexthop *nh, bool force,
 3786				char *ratr_pl)
 3787{
 3788	int i;
 3789
 3790	for (i = 0; i < nh->num_adj_entries; i++) {
 3791		int err;
 3792
 3793		err = __mlxsw_sp_nexthop_eth_update(mlxsw_sp, adj_index + i,
 3794						    nh, force, ratr_pl);
 3795		if (err)
 3796			return err;
 3797	}
 3798
 3799	return 0;
 3800}
 3801
 3802static int __mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp *mlxsw_sp,
 3803					  u32 adj_index,
 3804					  struct mlxsw_sp_nexthop *nh,
 3805					  bool force, char *ratr_pl)
 3806{
 3807	const struct mlxsw_sp_ipip_ops *ipip_ops;
 3808
 3809	ipip_ops = mlxsw_sp->router->ipip_ops_arr[nh->ipip_entry->ipipt];
 3810	return ipip_ops->nexthop_update(mlxsw_sp, adj_index, nh->ipip_entry,
 3811					force, ratr_pl);
 3812}
 3813
 3814static int mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp *mlxsw_sp,
 3815					u32 adj_index,
 3816					struct mlxsw_sp_nexthop *nh, bool force,
 3817					char *ratr_pl)
 3818{
 3819	int i;
 3820
 3821	for (i = 0; i < nh->num_adj_entries; i++) {
 3822		int err;
 3823
 3824		err = __mlxsw_sp_nexthop_ipip_update(mlxsw_sp, adj_index + i,
 3825						     nh, force, ratr_pl);
 3826		if (err)
 3827			return err;
 3828	}
 3829
 3830	return 0;
 3831}
 3832
 3833static int mlxsw_sp_nexthop_update(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
 3834				   struct mlxsw_sp_nexthop *nh, bool force,
 3835				   char *ratr_pl)
 3836{
 3837	/* When action is discard or trap, the nexthop must be
 3838	 * programmed as an Ethernet nexthop.
 3839	 */
 3840	if (nh->type == MLXSW_SP_NEXTHOP_TYPE_ETH ||
 3841	    nh->action == MLXSW_SP_NEXTHOP_ACTION_DISCARD ||
 3842	    nh->action == MLXSW_SP_NEXTHOP_ACTION_TRAP)
 3843		return mlxsw_sp_nexthop_eth_update(mlxsw_sp, adj_index, nh,
 3844						   force, ratr_pl);
 3845	else
 3846		return mlxsw_sp_nexthop_ipip_update(mlxsw_sp, adj_index, nh,
 3847						    force, ratr_pl);
 3848}
 3849
 3850static int
 3851mlxsw_sp_nexthop_group_update(struct mlxsw_sp *mlxsw_sp,
 3852			      struct mlxsw_sp_nexthop_group_info *nhgi,
 3853			      bool reallocate)
 3854{
 3855	char ratr_pl[MLXSW_REG_RATR_LEN];
 3856	u32 adj_index = nhgi->adj_index; /* base */
 3857	struct mlxsw_sp_nexthop *nh;
 3858	int i;
 3859
 3860	for (i = 0; i < nhgi->count; i++) {
 3861		nh = &nhgi->nexthops[i];
 3862
 3863		if (!nh->should_offload) {
 3864			mlxsw_sp_nexthop_counter_disable(mlxsw_sp, nh);
 3865			nh->offloaded = 0;
 3866			continue;
 3867		}
 3868
 3869		if (nh->update || reallocate) {
 3870			int err = 0;
 3871
 3872			err = mlxsw_sp_nexthop_counter_update(mlxsw_sp, nh);
 3873			if (err)
 3874				return err;
 3875
 3876			err = mlxsw_sp_nexthop_update(mlxsw_sp, adj_index, nh,
 3877						      true, ratr_pl);
 3878			if (err)
 3879				return err;
 3880			nh->update = 0;
 3881			nh->offloaded = 1;
 3882		}
 3883		adj_index += nh->num_adj_entries;
 3884	}
 3885	return 0;
 3886}
 3887
 3888static int
 3889mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp *mlxsw_sp,
 3890				    struct mlxsw_sp_nexthop_group *nh_grp)
 3891{
 3892	struct mlxsw_sp_fib_entry *fib_entry;
 3893	int err;
 3894
 3895	list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) {
 3896		err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
 3897		if (err)
 3898			return err;
 3899	}
 3900	return 0;
 3901}
 3902
 3903struct mlxsw_sp_adj_grp_size_range {
 3904	u16 start; /* Inclusive */
 3905	u16 end; /* Inclusive */
 3906};
 3907
 3908/* Ordered by range start value */
 3909static const struct mlxsw_sp_adj_grp_size_range
 3910mlxsw_sp1_adj_grp_size_ranges[] = {
 3911	{ .start = 1, .end = 64 },
 3912	{ .start = 512, .end = 512 },
 3913	{ .start = 1024, .end = 1024 },
 3914	{ .start = 2048, .end = 2048 },
 3915	{ .start = 4096, .end = 4096 },
 3916};
 3917
 3918/* Ordered by range start value */
 3919static const struct mlxsw_sp_adj_grp_size_range
 3920mlxsw_sp2_adj_grp_size_ranges[] = {
 3921	{ .start = 1, .end = 128 },
 3922	{ .start = 256, .end = 256 },
 3923	{ .start = 512, .end = 512 },
 3924	{ .start = 1024, .end = 1024 },
 3925	{ .start = 2048, .end = 2048 },
 3926	{ .start = 4096, .end = 4096 },
 3927};
 3928
 3929static void mlxsw_sp_adj_grp_size_round_up(const struct mlxsw_sp *mlxsw_sp,
 3930					   u16 *p_adj_grp_size)
 3931{
 3932	int i;
 3933
 3934	for (i = 0; i < mlxsw_sp->router->adj_grp_size_ranges_count; i++) {
 3935		const struct mlxsw_sp_adj_grp_size_range *size_range;
 3936
 3937		size_range = &mlxsw_sp->router->adj_grp_size_ranges[i];
 3938
 3939		if (*p_adj_grp_size >= size_range->start &&
 3940		    *p_adj_grp_size <= size_range->end)
 3941			return;
 3942
 3943		if (*p_adj_grp_size <= size_range->end) {
 3944			*p_adj_grp_size = size_range->end;
 3945			return;
 3946		}
 3947	}
 3948}
 3949
 3950static void mlxsw_sp_adj_grp_size_round_down(const struct mlxsw_sp *mlxsw_sp,
 3951					     u16 *p_adj_grp_size,
 3952					     unsigned int alloc_size)
 3953{
 3954	int i;
 3955
 3956	for (i = mlxsw_sp->router->adj_grp_size_ranges_count - 1; i >= 0; i--) {
 3957		const struct mlxsw_sp_adj_grp_size_range *size_range;
 3958
 3959		size_range = &mlxsw_sp->router->adj_grp_size_ranges[i];
 3960
 3961		if (alloc_size >= size_range->end) {
 3962			*p_adj_grp_size = size_range->end;
 3963			return;
 3964		}
 3965	}
 3966}
 3967
 3968static int mlxsw_sp_fix_adj_grp_size(struct mlxsw_sp *mlxsw_sp,
 3969				     u16 *p_adj_grp_size)
 3970{
 3971	unsigned int alloc_size;
 3972	int err;
 3973
 3974	/* Round up the requested group size to the next size supported
 3975	 * by the device and make sure the request can be satisfied.
 3976	 */
 3977	mlxsw_sp_adj_grp_size_round_up(mlxsw_sp, p_adj_grp_size);
 3978	err = mlxsw_sp_kvdl_alloc_count_query(mlxsw_sp,
 3979					      MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
 3980					      *p_adj_grp_size, &alloc_size);
 3981	if (err)
 3982		return err;
 3983	/* It is possible the allocation results in more allocated
 3984	 * entries than requested. Try to use as much of them as
 3985	 * possible.
 3986	 */
 3987	mlxsw_sp_adj_grp_size_round_down(mlxsw_sp, p_adj_grp_size, alloc_size);
 3988
 3989	return 0;
 3990}
 3991
 3992static void
 3993mlxsw_sp_nexthop_group_normalize(struct mlxsw_sp_nexthop_group_info *nhgi)
 3994{
 3995	int i, g = 0, sum_norm_weight = 0;
 3996	struct mlxsw_sp_nexthop *nh;
 3997
 3998	for (i = 0; i < nhgi->count; i++) {
 3999		nh = &nhgi->nexthops[i];
 4000
 4001		if (!nh->should_offload)
 4002			continue;
 4003		if (g > 0)
 4004			g = gcd(nh->nh_weight, g);
 4005		else
 4006			g = nh->nh_weight;
 4007	}
 4008
 4009	for (i = 0; i < nhgi->count; i++) {
 4010		nh = &nhgi->nexthops[i];
 4011
 4012		if (!nh->should_offload)
 4013			continue;
 4014		nh->norm_nh_weight = nh->nh_weight / g;
 4015		sum_norm_weight += nh->norm_nh_weight;
 4016	}
 4017
 4018	nhgi->sum_norm_weight = sum_norm_weight;
 4019}
 4020
 4021static void
 4022mlxsw_sp_nexthop_group_rebalance(struct mlxsw_sp_nexthop_group_info *nhgi)
 4023{
 4024	int i, weight = 0, lower_bound = 0;
 4025	int total = nhgi->sum_norm_weight;
 4026	u16 ecmp_size = nhgi->ecmp_size;
 4027
 4028	for (i = 0; i < nhgi->count; i++) {
 4029		struct mlxsw_sp_nexthop *nh = &nhgi->nexthops[i];
 4030		int upper_bound;
 4031
 4032		if (!nh->should_offload)
 4033			continue;
 4034		weight += nh->norm_nh_weight;
 4035		upper_bound = DIV_ROUND_CLOSEST(ecmp_size * weight, total);
 4036		nh->num_adj_entries = upper_bound - lower_bound;
 4037		lower_bound = upper_bound;
 4038	}
 4039}
 4040
 4041static struct mlxsw_sp_nexthop *
 4042mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
 4043		     const struct mlxsw_sp_rt6 *mlxsw_sp_rt6);
 4044
 4045static void
 4046mlxsw_sp_nexthop4_group_offload_refresh(struct mlxsw_sp *mlxsw_sp,
 4047					struct mlxsw_sp_nexthop_group *nh_grp)
 4048{
 4049	int i;
 4050
 4051	for (i = 0; i < nh_grp->nhgi->count; i++) {
 4052		struct mlxsw_sp_nexthop *nh = &nh_grp->nhgi->nexthops[i];
 4053
 4054		if (nh->offloaded)
 4055			nh->key.fib_nh->fib_nh_flags |= RTNH_F_OFFLOAD;
 4056		else
 4057			nh->key.fib_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
 4058	}
 4059}
 4060
 4061static void
 4062__mlxsw_sp_nexthop6_group_offload_refresh(struct mlxsw_sp_nexthop_group *nh_grp,
 4063					  struct mlxsw_sp_fib6_entry *fib6_entry)
 4064{
 4065	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
 4066
 4067	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
 4068		struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
 4069		struct mlxsw_sp_nexthop *nh;
 4070
 4071		nh = mlxsw_sp_rt6_nexthop(nh_grp, mlxsw_sp_rt6);
 4072		if (nh && nh->offloaded)
 4073			fib6_nh->fib_nh_flags |= RTNH_F_OFFLOAD;
 4074		else
 4075			fib6_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
 4076	}
 4077}
 4078
 4079static void
 4080mlxsw_sp_nexthop6_group_offload_refresh(struct mlxsw_sp *mlxsw_sp,
 4081					struct mlxsw_sp_nexthop_group *nh_grp)
 4082{
 4083	struct mlxsw_sp_fib6_entry *fib6_entry;
 4084
 4085	/* Unfortunately, in IPv6 the route and the nexthop are described by
 4086	 * the same struct, so we need to iterate over all the routes using the
 4087	 * nexthop group and set / clear the offload indication for them.
 4088	 */
 4089	list_for_each_entry(fib6_entry, &nh_grp->fib_list,
 4090			    common.nexthop_group_node)
 4091		__mlxsw_sp_nexthop6_group_offload_refresh(nh_grp, fib6_entry);
 4092}
 4093
 4094static void
 4095mlxsw_sp_nexthop_bucket_offload_refresh(struct mlxsw_sp *mlxsw_sp,
 4096					const struct mlxsw_sp_nexthop *nh,
 4097					u16 bucket_index)
 4098{
 4099	struct mlxsw_sp_nexthop_group *nh_grp = nh->nhgi->nh_grp;
 4100	bool offload = false, trap = false;
 4101
 4102	if (nh->offloaded) {
 4103		if (nh->action == MLXSW_SP_NEXTHOP_ACTION_TRAP)
 4104			trap = true;
 4105		else
 4106			offload = true;
 4107	}
 4108	nexthop_bucket_set_hw_flags(mlxsw_sp_net(mlxsw_sp), nh_grp->obj.id,
 4109				    bucket_index, offload, trap);
 4110}
 4111
 4112static void
 4113mlxsw_sp_nexthop_obj_group_offload_refresh(struct mlxsw_sp *mlxsw_sp,
 4114					   struct mlxsw_sp_nexthop_group *nh_grp)
 4115{
 4116	int i;
 4117
 4118	/* Do not update the flags if the nexthop group is being destroyed
 4119	 * since:
 4120	 * 1. The nexthop objects is being deleted, in which case the flags are
 4121	 * irrelevant.
 4122	 * 2. The nexthop group was replaced by a newer group, in which case
 4123	 * the flags of the nexthop object were already updated based on the
 4124	 * new group.
 4125	 */
 4126	if (nh_grp->can_destroy)
 4127		return;
 4128
 4129	nexthop_set_hw_flags(mlxsw_sp_net(mlxsw_sp), nh_grp->obj.id,
 4130			     nh_grp->nhgi->adj_index_valid, false);
 4131
 4132	/* Update flags of individual nexthop buckets in case of a resilient
 4133	 * nexthop group.
 4134	 */
 4135	if (!nh_grp->nhgi->is_resilient)
 4136		return;
 4137
 4138	for (i = 0; i < nh_grp->nhgi->count; i++) {
 4139		struct mlxsw_sp_nexthop *nh = &nh_grp->nhgi->nexthops[i];
 4140
 4141		mlxsw_sp_nexthop_bucket_offload_refresh(mlxsw_sp, nh, i);
 4142	}
 4143}
 4144
 4145static void
 4146mlxsw_sp_nexthop_group_offload_refresh(struct mlxsw_sp *mlxsw_sp,
 4147				       struct mlxsw_sp_nexthop_group *nh_grp)
 4148{
 4149	switch (nh_grp->type) {
 4150	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4:
 4151		mlxsw_sp_nexthop4_group_offload_refresh(mlxsw_sp, nh_grp);
 4152		break;
 4153	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6:
 4154		mlxsw_sp_nexthop6_group_offload_refresh(mlxsw_sp, nh_grp);
 4155		break;
 4156	case MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ:
 4157		mlxsw_sp_nexthop_obj_group_offload_refresh(mlxsw_sp, nh_grp);
 4158		break;
 4159	}
 4160}
 4161
 4162static int
 4163mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp *mlxsw_sp,
 4164			       struct mlxsw_sp_nexthop_group *nh_grp)
 4165{
 4166	struct mlxsw_sp_nexthop_group_info *nhgi = nh_grp->nhgi;
 4167	u16 ecmp_size, old_ecmp_size;
 4168	struct mlxsw_sp_nexthop *nh;
 4169	bool offload_change = false;
 4170	u32 adj_index;
 4171	bool old_adj_index_valid;
 4172	u32 old_adj_index;
 4173	int i, err2, err;
 4174
 4175	if (!nhgi->gateway)
 4176		return mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
 4177
 4178	for (i = 0; i < nhgi->count; i++) {
 4179		nh = &nhgi->nexthops[i];
 4180
 4181		if (nh->should_offload != nh->offloaded) {
 4182			offload_change = true;
 4183			if (nh->should_offload)
 4184				nh->update = 1;
 4185		}
 4186	}
 4187	if (!offload_change) {
 4188		/* Nothing was added or removed, so no need to reallocate. Just
 4189		 * update MAC on existing adjacency indexes.
 4190		 */
 4191		err = mlxsw_sp_nexthop_group_update(mlxsw_sp, nhgi, false);
 4192		if (err) {
 4193			dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
 4194			goto set_trap;
 4195		}
 4196		/* Flags of individual nexthop buckets might need to be
 4197		 * updated.
 4198		 */
 4199		mlxsw_sp_nexthop_group_offload_refresh(mlxsw_sp, nh_grp);
 4200		return 0;
 4201	}
 4202	mlxsw_sp_nexthop_group_normalize(nhgi);
 4203	if (!nhgi->sum_norm_weight) {
 4204		/* No neigh of this group is connected so we just set
 4205		 * the trap and let everthing flow through kernel.
 4206		 */
 4207		err = 0;
 4208		goto set_trap;
 4209	}
 4210
 4211	ecmp_size = nhgi->sum_norm_weight;
 4212	err = mlxsw_sp_fix_adj_grp_size(mlxsw_sp, &ecmp_size);
 4213	if (err)
 4214		/* No valid allocation size available. */
 4215		goto set_trap;
 4216
 4217	err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
 4218				  ecmp_size, &adj_index);
 4219	if (err) {
 4220		/* We ran out of KVD linear space, just set the
 4221		 * trap and let everything flow through kernel.
 4222		 */
 4223		dev_warn(mlxsw_sp->bus_info->dev, "Failed to allocate KVD linear area for nexthop group.\n");
 4224		goto set_trap;
 4225	}
 4226	old_adj_index_valid = nhgi->adj_index_valid;
 4227	old_adj_index = nhgi->adj_index;
 4228	old_ecmp_size = nhgi->ecmp_size;
 4229	nhgi->adj_index_valid = 1;
 4230	nhgi->adj_index = adj_index;
 4231	nhgi->ecmp_size = ecmp_size;
 4232	mlxsw_sp_nexthop_group_rebalance(nhgi);
 4233	err = mlxsw_sp_nexthop_group_update(mlxsw_sp, nhgi, true);
 4234	if (err) {
 4235		dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
 4236		goto set_trap;
 4237	}
 4238
 4239	mlxsw_sp_nexthop_group_offload_refresh(mlxsw_sp, nh_grp);
 4240
 4241	if (!old_adj_index_valid) {
 4242		/* The trap was set for fib entries, so we have to call
 4243		 * fib entry update to unset it and use adjacency index.
 4244		 */
 4245		err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
 4246		if (err) {
 4247			dev_warn(mlxsw_sp->bus_info->dev, "Failed to add adjacency index to fib entries.\n");
 4248			goto set_trap;
 4249		}
 4250		return 0;
 4251	}
 4252
 4253	err = mlxsw_sp_adj_index_mass_update(mlxsw_sp, nh_grp,
 4254					     old_adj_index, old_ecmp_size);
 4255	mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
 4256			   old_ecmp_size, old_adj_index);
 4257	if (err) {
 4258		dev_warn(mlxsw_sp->bus_info->dev, "Failed to mass-update adjacency index for nexthop group.\n");
 4259		goto set_trap;
 4260	}
 4261
 4262	return 0;
 4263
 4264set_trap:
 4265	old_adj_index_valid = nhgi->adj_index_valid;
 4266	nhgi->adj_index_valid = 0;
 4267	for (i = 0; i < nhgi->count; i++) {
 4268		nh = &nhgi->nexthops[i];
 4269		nh->offloaded = 0;
 4270	}
 4271	err2 = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
 4272	if (err2)
 4273		dev_warn(mlxsw_sp->bus_info->dev, "Failed to set traps for fib entries.\n");
 4274	mlxsw_sp_nexthop_group_offload_refresh(mlxsw_sp, nh_grp);
 4275	if (old_adj_index_valid)
 4276		mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
 4277				   nhgi->ecmp_size, nhgi->adj_index);
 4278	return err;
 4279}
 4280
 4281static void __mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp_nexthop *nh,
 4282					    bool removing)
 4283{
 4284	if (!removing) {
 4285		nh->action = MLXSW_SP_NEXTHOP_ACTION_FORWARD;
 4286		nh->should_offload = 1;
 4287	} else if (nh->nhgi->is_resilient) {
 4288		nh->action = MLXSW_SP_NEXTHOP_ACTION_TRAP;
 4289		nh->should_offload = 1;
 4290	} else {
 4291		nh->should_offload = 0;
 4292	}
 4293	nh->update = 1;
 4294}
 4295
 4296static int
 4297mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
 4298				    struct mlxsw_sp_neigh_entry *neigh_entry)
 4299{
 4300	struct neighbour *n, *old_n = neigh_entry->key.n;
 4301	struct mlxsw_sp_nexthop *nh;
 4302	struct net_device *dev;
 4303	bool entry_connected;
 4304	u8 nud_state, dead;
 4305	int err;
 4306
 4307	nh = list_first_entry(&neigh_entry->nexthop_list,
 4308			      struct mlxsw_sp_nexthop, neigh_list_node);
 4309	dev = mlxsw_sp_nexthop_dev(nh);
 4310
 4311	n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, dev);
 4312	if (!n) {
 4313		n = neigh_create(nh->neigh_tbl, &nh->gw_addr, dev);
 4314		if (IS_ERR(n))
 4315			return PTR_ERR(n);
 4316		neigh_event_send(n, NULL);
 4317	}
 4318
 4319	mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry);
 4320	neigh_entry->key.n = n;
 4321	err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
 4322	if (err)
 4323		goto err_neigh_entry_insert;
 4324
 4325	neigh_release(old_n);
 4326
 4327	read_lock_bh(&n->lock);
 4328	nud_state = n->nud_state;
 4329	dead = n->dead;
 4330	read_unlock_bh(&n->lock);
 4331	entry_connected = nud_state & NUD_VALID && !dead;
 4332
 4333	list_for_each_entry(nh, &neigh_entry->nexthop_list,
 4334			    neigh_list_node) {
 4335		__mlxsw_sp_nexthop_neigh_update(nh, !entry_connected);
 4336		mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
 4337	}
 4338
 4339	return 0;
 4340
 4341err_neigh_entry_insert:
 4342	neigh_entry->key.n = old_n;
 4343	mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
 4344	neigh_release(n);
 4345	return err;
 4346}
 4347
 4348static void
 4349mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
 4350			      struct mlxsw_sp_neigh_entry *neigh_entry,
 4351			      bool removing, bool dead)
 4352{
 4353	struct mlxsw_sp_nexthop *nh;
 4354
 4355	if (list_empty(&neigh_entry->nexthop_list))
 4356		return;
 4357
 4358	if (dead) {
 4359		int err;
 4360
 4361		err = mlxsw_sp_nexthop_dead_neigh_replace(mlxsw_sp,
 4362							  neigh_entry);
 4363		if (err)
 4364			dev_err(mlxsw_sp->bus_info->dev, "Failed to replace dead neigh\n");
 4365		return;
 4366	}
 4367
 4368	list_for_each_entry(nh, &neigh_entry->nexthop_list,
 4369			    neigh_list_node) {
 4370		__mlxsw_sp_nexthop_neigh_update(nh, removing);
 4371		mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
 4372	}
 4373}
 4374
 4375static void mlxsw_sp_nexthop_crif_init(struct mlxsw_sp_nexthop *nh,
 4376				       struct mlxsw_sp_crif *crif)
 4377{
 4378	if (nh->crif)
 4379		return;
 4380
 4381	nh->crif = crif;
 4382	list_add(&nh->crif_list_node, &crif->nexthop_list);
 4383}
 4384
 4385static void mlxsw_sp_nexthop_crif_fini(struct mlxsw_sp_nexthop *nh)
 4386{
 4387	if (!nh->crif)
 4388		return;
 4389
 4390	list_del(&nh->crif_list_node);
 4391	nh->crif = NULL;
 4392}
 4393
 4394static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp,
 4395				       struct mlxsw_sp_nexthop *nh)
 4396{
 4397	struct mlxsw_sp_neigh_entry *neigh_entry;
 4398	struct net_device *dev;
 4399	struct neighbour *n;
 4400	u8 nud_state, dead;
 4401	int err;
 4402
 4403	if (WARN_ON(!nh->crif->rif))
 4404		return 0;
 4405
 4406	if (!nh->nhgi->gateway || nh->neigh_entry)
 4407		return 0;
 4408	dev = mlxsw_sp_nexthop_dev(nh);
 4409
 4410	/* Take a reference of neigh here ensuring that neigh would
 4411	 * not be destructed before the nexthop entry is finished.
 4412	 * The reference is taken either in neigh_lookup() or
 4413	 * in neigh_create() in case n is not found.
 4414	 */
 4415	n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, dev);
 4416	if (!n) {
 4417		n = neigh_create(nh->neigh_tbl, &nh->gw_addr, dev);
 4418		if (IS_ERR(n))
 4419			return PTR_ERR(n);
 4420		neigh_event_send(n, NULL);
 4421	}
 4422	neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
 4423	if (!neigh_entry) {
 4424		neigh_entry = mlxsw_sp_neigh_entry_create(mlxsw_sp, n);
 4425		if (IS_ERR(neigh_entry)) {
 4426			err = -EINVAL;
 4427			goto err_neigh_entry_create;
 4428		}
 4429	}
 4430
 4431	/* Release the reference taken by neigh_lookup() / neigh_create() since
 4432	 * neigh_entry already holds one.
 4433	 */
 4434	neigh_release(n);
 4435
 4436	/* If that is the first nexthop connected to that neigh, add to
 4437	 * nexthop_neighs_list
 4438	 */
 4439	if (list_empty(&neigh_entry->nexthop_list))
 4440		list_add_tail(&neigh_entry->nexthop_neighs_list_node,
 4441			      &mlxsw_sp->router->nexthop_neighs_list);
 4442
 4443	nh->neigh_entry = neigh_entry;
 4444	list_add_tail(&nh->neigh_list_node, &neigh_entry->nexthop_list);
 4445	read_lock_bh(&n->lock);
 4446	nud_state = n->nud_state;
 4447	dead = n->dead;
 4448	read_unlock_bh(&n->lock);
 4449	__mlxsw_sp_nexthop_neigh_update(nh, !(nud_state & NUD_VALID && !dead));
 4450
 4451	return 0;
 4452
 4453err_neigh_entry_create:
 4454	neigh_release(n);
 4455	return err;
 4456}
 4457
 4458static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
 4459					struct mlxsw_sp_nexthop *nh)
 4460{
 4461	struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
 4462
 4463	if (!neigh_entry)
 4464		return;
 4465
 4466	__mlxsw_sp_nexthop_neigh_update(nh, true);
 4467	list_del(&nh->neigh_list_node);
 4468	nh->neigh_entry = NULL;
 4469
 4470	/* If that is the last nexthop connected to that neigh, remove from
 4471	 * nexthop_neighs_list
 4472	 */
 4473	if (list_empty(&neigh_entry->nexthop_list))
 4474		list_del(&neigh_entry->nexthop_neighs_list_node);
 4475
 4476	if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
 4477		mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
 4478}
 4479
 4480static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev)
 4481{
 4482	struct net_device *ul_dev;
 4483	bool is_up;
 4484
 4485	rcu_read_lock();
 4486	ul_dev = mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
 4487	is_up = ul_dev ? (ul_dev->flags & IFF_UP) : true;
 4488	rcu_read_unlock();
 4489
 4490	return is_up;
 4491}
 4492
 4493static void mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp,
 4494				       struct mlxsw_sp_nexthop *nh,
 4495				       struct mlxsw_sp_ipip_entry *ipip_entry)
 4496{
 4497	struct mlxsw_sp_crif *crif;
 4498	bool removing;
 4499
 4500	if (!nh->nhgi->gateway || nh->ipip_entry)
 4501		return;
 4502
 4503	crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, ipip_entry->ol_dev);
 4504	if (WARN_ON(!crif))
 4505		return;
 4506
 4507	nh->ipip_entry = ipip_entry;
 4508	removing = !mlxsw_sp_ipip_netdev_ul_up(ipip_entry->ol_dev);
 4509	__mlxsw_sp_nexthop_neigh_update(nh, removing);
 4510	mlxsw_sp_nexthop_crif_init(nh, crif);
 4511}
 4512
 4513static void mlxsw_sp_nexthop_ipip_fini(struct mlxsw_sp *mlxsw_sp,
 4514				       struct mlxsw_sp_nexthop *nh)
 4515{
 4516	struct mlxsw_sp_ipip_entry *ipip_entry = nh->ipip_entry;
 4517
 4518	if (!ipip_entry)
 4519		return;
 4520
 4521	__mlxsw_sp_nexthop_neigh_update(nh, true);
 4522	nh->ipip_entry = NULL;
 4523}
 4524
 4525static bool mlxsw_sp_nexthop4_ipip_type(const struct mlxsw_sp *mlxsw_sp,
 4526					const struct fib_nh *fib_nh,
 4527					enum mlxsw_sp_ipip_type *p_ipipt)
 4528{
 4529	struct net_device *dev = fib_nh->fib_nh_dev;
 4530
 4531	return dev &&
 4532	       fib_nh->nh_parent->fib_type == RTN_UNICAST &&
 4533	       mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, p_ipipt);
 4534}
 4535
 4536static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp,
 4537				      struct mlxsw_sp_nexthop *nh,
 4538				      const struct net_device *dev)
 4539{
 4540	const struct mlxsw_sp_ipip_ops *ipip_ops;
 4541	struct mlxsw_sp_ipip_entry *ipip_entry;
 4542	struct mlxsw_sp_crif *crif;
 4543	int err;
 4544
 4545	ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, dev);
 4546	if (ipip_entry) {
 4547		ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
 4548		if (ipip_ops->can_offload(mlxsw_sp, dev)) {
 4549			nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP;
 4550			mlxsw_sp_nexthop_ipip_init(mlxsw_sp, nh, ipip_entry);
 4551			return 0;
 4552		}
 4553	}
 4554
 4555	nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
 4556	crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, dev);
 4557	if (!crif)
 4558		return 0;
 4559
 4560	mlxsw_sp_nexthop_crif_init(nh, crif);
 4561
 4562	if (!crif->rif)
 4563		return 0;
 4564
 4565	err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
 4566	if (err)
 4567		goto err_neigh_init;
 4568
 4569	return 0;
 4570
 4571err_neigh_init:
 4572	mlxsw_sp_nexthop_crif_fini(nh);
 4573	return err;
 4574}
 4575
 4576static int mlxsw_sp_nexthop_type_rif_made(struct mlxsw_sp *mlxsw_sp,
 4577					  struct mlxsw_sp_nexthop *nh)
 4578{
 4579	switch (nh->type) {
 4580	case MLXSW_SP_NEXTHOP_TYPE_ETH:
 4581		return mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
 4582	case MLXSW_SP_NEXTHOP_TYPE_IPIP:
 4583		break;
 4584	}
 4585
 4586	return 0;
 4587}
 4588
 4589static void mlxsw_sp_nexthop_type_rif_gone(struct mlxsw_sp *mlxsw_sp,
 4590					   struct mlxsw_sp_nexthop *nh)
 4591{
 4592	switch (nh->type) {
 4593	case MLXSW_SP_NEXTHOP_TYPE_ETH:
 4594		mlxsw_sp_nexthop_neigh_fini(mlxsw_sp, nh);
 4595		break;
 4596	case MLXSW_SP_NEXTHOP_TYPE_IPIP:
 4597		mlxsw_sp_nexthop_ipip_fini(mlxsw_sp, nh);
 4598		break;
 4599	}
 4600}
 4601
 4602static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
 4603				       struct mlxsw_sp_nexthop *nh)
 4604{
 4605	mlxsw_sp_nexthop_type_rif_gone(mlxsw_sp, nh);
 4606	mlxsw_sp_nexthop_crif_fini(nh);
 4607}
 4608
 4609static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
 4610				  struct mlxsw_sp_nexthop_group *nh_grp,
 4611				  struct mlxsw_sp_nexthop *nh,
 4612				  struct fib_nh *fib_nh)
 4613{
 4614	struct net_device *dev = fib_nh->fib_nh_dev;
 4615	struct in_device *in_dev;
 4616	int err;
 4617
 4618	nh->nhgi = nh_grp->nhgi;
 4619	nh->key.fib_nh = fib_nh;
 4620#ifdef CONFIG_IP_ROUTE_MULTIPATH
 4621	nh->nh_weight = fib_nh->fib_nh_weight;
 4622#else
 4623	nh->nh_weight = 1;
 4624#endif
 4625	memcpy(&nh->gw_addr, &fib_nh->fib_nh_gw4, sizeof(fib_nh->fib_nh_gw4));
 4626	nh->neigh_tbl = &arp_tbl;
 4627	err = mlxsw_sp_nexthop_insert(mlxsw_sp, nh);
 4628	if (err)
 4629		return err;
 4630
 4631	err = mlxsw_sp_nexthop_counter_enable(mlxsw_sp, nh);
 4632	if (err)
 4633		goto err_counter_enable;
 4634
 4635	list_add_tail(&nh->router_list_node, &mlxsw_sp->router->nexthop_list);
 4636
 4637	if (!dev)
 4638		return 0;
 4639	nh->ifindex = dev->ifindex;
 4640
 4641	rcu_read_lock();
 4642	in_dev = __in_dev_get_rcu(dev);
 4643	if (in_dev && IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev) &&
 4644	    fib_nh->fib_nh_flags & RTNH_F_LINKDOWN) {
 4645		rcu_read_unlock();
 4646		return 0;
 4647	}
 4648	rcu_read_unlock();
 4649
 4650	err = mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
 4651	if (err)
 4652		goto err_nexthop_neigh_init;
 4653
 4654	return 0;
 4655
 4656err_nexthop_neigh_init:
 4657	list_del(&nh->router_list_node);
 4658	mlxsw_sp_nexthop_counter_disable(mlxsw_sp, nh);
 4659err_counter_enable:
 4660	mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
 4661	return err;
 4662}
 4663
 4664static void mlxsw_sp_nexthop4_fini(struct mlxsw_sp *mlxsw_sp,
 4665				   struct mlxsw_sp_nexthop *nh)
 4666{
 4667	mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
 4668	list_del(&nh->router_list_node);
 4669	mlxsw_sp_nexthop_counter_disable(mlxsw_sp, nh);
 4670	mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
 4671}
 4672
 4673static void mlxsw_sp_nexthop4_event(struct mlxsw_sp *mlxsw_sp,
 4674				    unsigned long event, struct fib_nh *fib_nh)
 4675{
 4676	struct mlxsw_sp_nexthop_key key;
 4677	struct mlxsw_sp_nexthop *nh;
 4678
 4679	key.fib_nh = fib_nh;
 4680	nh = mlxsw_sp_nexthop_lookup(mlxsw_sp, key);
 4681	if (!nh)
 4682		return;
 4683
 4684	switch (event) {
 4685	case FIB_EVENT_NH_ADD:
 4686		mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, fib_nh->fib_nh_dev);
 4687		break;
 4688	case FIB_EVENT_NH_DEL:
 4689		mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
 4690		break;
 4691	}
 4692
 4693	mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
 4694}
 4695
 4696static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
 4697					struct mlxsw_sp_rif *rif)
 4698{
 4699	struct net_device *dev = mlxsw_sp_rif_dev(rif);
 4700	struct mlxsw_sp_nexthop *nh;
 4701	bool removing;
 4702
 4703	list_for_each_entry(nh, &rif->crif->nexthop_list, crif_list_node) {
 4704		switch (nh->type) {
 4705		case MLXSW_SP_NEXTHOP_TYPE_ETH:
 4706			removing = false;
 4707			break;
 4708		case MLXSW_SP_NEXTHOP_TYPE_IPIP:
 4709			removing = !mlxsw_sp_ipip_netdev_ul_up(dev);
 4710			break;
 4711		default:
 4712			WARN_ON(1);
 4713			continue;
 4714		}
 4715
 4716		__mlxsw_sp_nexthop_neigh_update(nh, removing);
 4717		mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
 4718	}
 4719}
 4720
 4721static int mlxsw_sp_nexthop_rif_made_sync(struct mlxsw_sp *mlxsw_sp,
 4722					  struct mlxsw_sp_rif *rif)
 4723{
 4724	struct mlxsw_sp_nexthop *nh, *tmp;
 4725	unsigned int n = 0;
 4726	int err;
 4727
 4728	list_for_each_entry_safe(nh, tmp, &rif->crif->nexthop_list,
 4729				 crif_list_node) {
 4730		err = mlxsw_sp_nexthop_type_rif_made(mlxsw_sp, nh);
 4731		if (err)
 4732			goto err_nexthop_type_rif;
 4733		mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
 4734		n++;
 4735	}
 4736
 4737	return 0;
 4738
 4739err_nexthop_type_rif:
 4740	list_for_each_entry_safe(nh, tmp, &rif->crif->nexthop_list,
 4741				 crif_list_node) {
 4742		if (!n--)
 4743			break;
 4744		mlxsw_sp_nexthop_type_rif_gone(mlxsw_sp, nh);
 4745		mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
 4746	}
 4747	return err;
 4748}
 4749
 4750static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
 4751					   struct mlxsw_sp_rif *rif)
 4752{
 4753	struct mlxsw_sp_nexthop *nh, *tmp;
 4754
 4755	list_for_each_entry_safe(nh, tmp, &rif->crif->nexthop_list,
 4756				 crif_list_node) {
 4757		mlxsw_sp_nexthop_type_rif_gone(mlxsw_sp, nh);
 4758		mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
 4759	}
 4760}
 4761
 4762static int mlxsw_sp_adj_trap_entry_init(struct mlxsw_sp *mlxsw_sp)
 4763{
 4764	enum mlxsw_reg_ratr_trap_action trap_action;
 4765	char ratr_pl[MLXSW_REG_RATR_LEN];
 4766	int err;
 4767
 4768	err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
 4769				  &mlxsw_sp->router->adj_trap_index);
 4770	if (err)
 4771		return err;
 4772
 4773	trap_action = MLXSW_REG_RATR_TRAP_ACTION_TRAP;
 4774	mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY, true,
 4775			    MLXSW_REG_RATR_TYPE_ETHERNET,
 4776			    mlxsw_sp->router->adj_trap_index,
 4777			    mlxsw_sp->router->lb_crif->rif->rif_index);
 4778	mlxsw_reg_ratr_trap_action_set(ratr_pl, trap_action);
 4779	mlxsw_reg_ratr_trap_id_set(ratr_pl, MLXSW_TRAP_ID_RTR_EGRESS0);
 4780	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
 4781	if (err)
 4782		goto err_ratr_write;
 4783
 4784	return 0;
 4785
 4786err_ratr_write:
 4787	mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
 4788			   mlxsw_sp->router->adj_trap_index);
 4789	return err;
 4790}
 4791
 4792static void mlxsw_sp_adj_trap_entry_fini(struct mlxsw_sp *mlxsw_sp)
 4793{
 4794	mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
 4795			   mlxsw_sp->router->adj_trap_index);
 4796}
 4797
 4798static int mlxsw_sp_nexthop_group_inc(struct mlxsw_sp *mlxsw_sp)
 4799{
 4800	int err;
 4801
 4802	if (refcount_inc_not_zero(&mlxsw_sp->router->num_groups))
 4803		return 0;
 4804
 4805	err = mlxsw_sp_adj_trap_entry_init(mlxsw_sp);
 4806	if (err)
 4807		return err;
 4808
 4809	refcount_set(&mlxsw_sp->router->num_groups, 1);
 4810
 4811	return 0;
 4812}
 4813
 4814static void mlxsw_sp_nexthop_group_dec(struct mlxsw_sp *mlxsw_sp)
 4815{
 4816	if (!refcount_dec_and_test(&mlxsw_sp->router->num_groups))
 4817		return;
 4818
 4819	mlxsw_sp_adj_trap_entry_fini(mlxsw_sp);
 4820}
 4821
 4822static void
 4823mlxsw_sp_nh_grp_activity_get(struct mlxsw_sp *mlxsw_sp,
 4824			     const struct mlxsw_sp_nexthop_group *nh_grp,
 4825			     unsigned long *activity)
 4826{
 4827	char *ratrad_pl;
 4828	int i, err;
 4829
 4830	ratrad_pl = kmalloc(MLXSW_REG_RATRAD_LEN, GFP_KERNEL);
 4831	if (!ratrad_pl)
 4832		return;
 4833
 4834	mlxsw_reg_ratrad_pack(ratrad_pl, nh_grp->nhgi->adj_index,
 4835			      nh_grp->nhgi->count);
 4836	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ratrad), ratrad_pl);
 4837	if (err)
 4838		goto out;
 4839
 4840	for (i = 0; i < nh_grp->nhgi->count; i++) {
 4841		if (!mlxsw_reg_ratrad_activity_vector_get(ratrad_pl, i))
 4842			continue;
 4843		bitmap_set(activity, i, 1);
 4844	}
 4845
 4846out:
 4847	kfree(ratrad_pl);
 4848}
 4849
 4850#define MLXSW_SP_NH_GRP_ACTIVITY_UPDATE_INTERVAL 1000 /* ms */
 4851
 4852static void
 4853mlxsw_sp_nh_grp_activity_update(struct mlxsw_sp *mlxsw_sp,
 4854				const struct mlxsw_sp_nexthop_group *nh_grp)
 4855{
 4856	unsigned long *activity;
 4857
 4858	activity = bitmap_zalloc(nh_grp->nhgi->count, GFP_KERNEL);
 4859	if (!activity)
 4860		return;
 4861
 4862	mlxsw_sp_nh_grp_activity_get(mlxsw_sp, nh_grp, activity);
 4863	nexthop_res_grp_activity_update(mlxsw_sp_net(mlxsw_sp), nh_grp->obj.id,
 4864					nh_grp->nhgi->count, activity);
 4865
 4866	bitmap_free(activity);
 4867}
 4868
 4869static void
 4870mlxsw_sp_nh_grp_activity_work_schedule(struct mlxsw_sp *mlxsw_sp)
 4871{
 4872	unsigned int interval = MLXSW_SP_NH_GRP_ACTIVITY_UPDATE_INTERVAL;
 4873
 4874	mlxsw_core_schedule_dw(&mlxsw_sp->router->nh_grp_activity_dw,
 4875			       msecs_to_jiffies(interval));
 4876}
 4877
 4878static void mlxsw_sp_nh_grp_activity_work(struct work_struct *work)
 4879{
 4880	struct mlxsw_sp_nexthop_group_info *nhgi;
 4881	struct mlxsw_sp_router *router;
 4882	bool reschedule = false;
 4883
 4884	router = container_of(work, struct mlxsw_sp_router,
 4885			      nh_grp_activity_dw.work);
 4886
 4887	mutex_lock(&router->lock);
 4888
 4889	list_for_each_entry(nhgi, &router->nh_res_grp_list, list) {
 4890		mlxsw_sp_nh_grp_activity_update(router->mlxsw_sp, nhgi->nh_grp);
 4891		reschedule = true;
 4892	}
 4893
 4894	mutex_unlock(&router->lock);
 4895
 4896	if (!reschedule)
 4897		return;
 4898	mlxsw_sp_nh_grp_activity_work_schedule(router->mlxsw_sp);
 4899}
 4900
 4901static int
 4902mlxsw_sp_nexthop_obj_single_validate(struct mlxsw_sp *mlxsw_sp,
 4903				     const struct nh_notifier_single_info *nh,
 4904				     struct netlink_ext_ack *extack)
 4905{
 4906	int err = -EINVAL;
 4907
 4908	if (nh->is_fdb)
 4909		NL_SET_ERR_MSG_MOD(extack, "FDB nexthops are not supported");
 4910	else if (nh->has_encap)
 4911		NL_SET_ERR_MSG_MOD(extack, "Encapsulating nexthops are not supported");
 4912	else
 4913		err = 0;
 4914
 4915	return err;
 4916}
 4917
 4918static int
 4919mlxsw_sp_nexthop_obj_group_entry_validate(struct mlxsw_sp *mlxsw_sp,
 4920					  const struct nh_notifier_single_info *nh,
 4921					  struct netlink_ext_ack *extack)
 4922{
 4923	int err;
 4924
 4925	err = mlxsw_sp_nexthop_obj_single_validate(mlxsw_sp, nh, extack);
 4926	if (err)
 4927		return err;
 4928
 4929	/* Device only nexthops with an IPIP device are programmed as
 4930	 * encapsulating adjacency entries.
 4931	 */
 4932	if (!nh->gw_family && !nh->is_reject &&
 4933	    !mlxsw_sp_netdev_ipip_type(mlxsw_sp, nh->dev, NULL)) {
 4934		NL_SET_ERR_MSG_MOD(extack, "Nexthop group entry does not have a gateway");
 4935		return -EINVAL;
 4936	}
 4937
 4938	return 0;
 4939}
 4940
 4941static int
 4942mlxsw_sp_nexthop_obj_group_validate(struct mlxsw_sp *mlxsw_sp,
 4943				    const struct nh_notifier_grp_info *nh_grp,
 4944				    struct netlink_ext_ack *extack)
 4945{
 4946	int i;
 4947
 4948	if (nh_grp->is_fdb) {
 4949		NL_SET_ERR_MSG_MOD(extack, "FDB nexthop groups are not supported");
 4950		return -EINVAL;
 4951	}
 4952
 4953	for (i = 0; i < nh_grp->num_nh; i++) {
 4954		const struct nh_notifier_single_info *nh;
 4955		int err;
 4956
 4957		nh = &nh_grp->nh_entries[i].nh;
 4958		err = mlxsw_sp_nexthop_obj_group_entry_validate(mlxsw_sp, nh,
 4959								extack);
 4960		if (err)
 4961			return err;
 4962	}
 4963
 4964	return 0;
 4965}
 4966
 4967static int
 4968mlxsw_sp_nexthop_obj_res_group_size_validate(struct mlxsw_sp *mlxsw_sp,
 4969					     const struct nh_notifier_res_table_info *nh_res_table,
 4970					     struct netlink_ext_ack *extack)
 4971{
 4972	unsigned int alloc_size;
 4973	bool valid_size = false;
 4974	int err, i;
 4975
 4976	if (nh_res_table->num_nh_buckets < 32) {
 4977		NL_SET_ERR_MSG_MOD(extack, "Minimum number of buckets is 32");
 4978		return -EINVAL;
 4979	}
 4980
 4981	for (i = 0; i < mlxsw_sp->router->adj_grp_size_ranges_count; i++) {
 4982		const struct mlxsw_sp_adj_grp_size_range *size_range;
 4983
 4984		size_range = &mlxsw_sp->router->adj_grp_size_ranges[i];
 4985
 4986		if (nh_res_table->num_nh_buckets >= size_range->start &&
 4987		    nh_res_table->num_nh_buckets <= size_range->end) {
 4988			valid_size = true;
 4989			break;
 4990		}
 4991	}
 4992
 4993	if (!valid_size) {
 4994		NL_SET_ERR_MSG_MOD(extack, "Invalid number of buckets");
 4995		return -EINVAL;
 4996	}
 4997
 4998	err = mlxsw_sp_kvdl_alloc_count_query(mlxsw_sp,
 4999					      MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
 5000					      nh_res_table->num_nh_buckets,
 5001					      &alloc_size);
 5002	if (err || nh_res_table->num_nh_buckets != alloc_size) {
 5003		NL_SET_ERR_MSG_MOD(extack, "Number of buckets does not fit allocation size of any KVDL partition");
 5004		return -EINVAL;
 5005	}
 5006
 5007	return 0;
 5008}
 5009
 5010static int
 5011mlxsw_sp_nexthop_obj_res_group_validate(struct mlxsw_sp *mlxsw_sp,
 5012					const struct nh_notifier_res_table_info *nh_res_table,
 5013					struct netlink_ext_ack *extack)
 5014{
 5015	int err;
 5016	u16 i;
 5017
 5018	err = mlxsw_sp_nexthop_obj_res_group_size_validate(mlxsw_sp,
 5019							   nh_res_table,
 5020							   extack);
 5021	if (err)
 5022		return err;
 5023
 5024	for (i = 0; i < nh_res_table->num_nh_buckets; i++) {
 5025		const struct nh_notifier_single_info *nh;
 5026		int err;
 5027
 5028		nh = &nh_res_table->nhs[i];
 5029		err = mlxsw_sp_nexthop_obj_group_entry_validate(mlxsw_sp, nh,
 5030								extack);
 5031		if (err)
 5032			return err;
 5033	}
 5034
 5035	return 0;
 5036}
 5037
 5038static int mlxsw_sp_nexthop_obj_validate(struct mlxsw_sp *mlxsw_sp,
 5039					 unsigned long event,
 5040					 struct nh_notifier_info *info)
 5041{
 5042	struct nh_notifier_single_info *nh;
 5043
 5044	if (event != NEXTHOP_EVENT_REPLACE &&
 5045	    event != NEXTHOP_EVENT_RES_TABLE_PRE_REPLACE &&
 5046	    event != NEXTHOP_EVENT_BUCKET_REPLACE)
 5047		return 0;
 5048
 5049	switch (info->type) {
 5050	case NH_NOTIFIER_INFO_TYPE_SINGLE:
 5051		return mlxsw_sp_nexthop_obj_single_validate(mlxsw_sp, info->nh,
 5052							    info->extack);
 5053	case NH_NOTIFIER_INFO_TYPE_GRP:
 5054		return mlxsw_sp_nexthop_obj_group_validate(mlxsw_sp,
 5055							   info->nh_grp,
 5056							   info->extack);
 5057	case NH_NOTIFIER_INFO_TYPE_RES_TABLE:
 5058		return mlxsw_sp_nexthop_obj_res_group_validate(mlxsw_sp,
 5059							       info->nh_res_table,
 5060							       info->extack);
 5061	case NH_NOTIFIER_INFO_TYPE_RES_BUCKET:
 5062		nh = &info->nh_res_bucket->new_nh;
 5063		return mlxsw_sp_nexthop_obj_group_entry_validate(mlxsw_sp, nh,
 5064								 info->extack);
 5065	default:
 5066		NL_SET_ERR_MSG_MOD(info->extack, "Unsupported nexthop type");
 5067		return -EOPNOTSUPP;
 5068	}
 5069}
 5070
 5071static bool mlxsw_sp_nexthop_obj_is_gateway(struct mlxsw_sp *mlxsw_sp,
 5072					    const struct nh_notifier_info *info)
 5073{
 5074	const struct net_device *dev;
 5075
 5076	switch (info->type) {
 5077	case NH_NOTIFIER_INFO_TYPE_SINGLE:
 5078		dev = info->nh->dev;
 5079		return info->nh->gw_family || info->nh->is_reject ||
 5080		       mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL);
 5081	case NH_NOTIFIER_INFO_TYPE_GRP:
 5082	case NH_NOTIFIER_INFO_TYPE_RES_TABLE:
 5083		/* Already validated earlier. */
 5084		return true;
 5085	default:
 5086		return false;
 5087	}
 5088}
 5089
 5090static void mlxsw_sp_nexthop_obj_blackhole_init(struct mlxsw_sp *mlxsw_sp,
 5091						struct mlxsw_sp_nexthop *nh)
 5092{
 5093	nh->action = MLXSW_SP_NEXTHOP_ACTION_DISCARD;
 5094	nh->should_offload = 1;
 5095	/* While nexthops that discard packets do not forward packets
 5096	 * via an egress RIF, they still need to be programmed using a
 5097	 * valid RIF, so use the loopback RIF created during init.
 5098	 */
 5099	nh->crif = mlxsw_sp->router->lb_crif;
 5100}
 5101
 5102static void mlxsw_sp_nexthop_obj_blackhole_fini(struct mlxsw_sp *mlxsw_sp,
 5103						struct mlxsw_sp_nexthop *nh)
 5104{
 5105	nh->crif = NULL;
 5106	nh->should_offload = 0;
 5107}
 5108
 5109static int
 5110mlxsw_sp_nexthop_obj_init(struct mlxsw_sp *mlxsw_sp,
 5111			  struct mlxsw_sp_nexthop_group *nh_grp,
 5112			  struct mlxsw_sp_nexthop *nh,
 5113			  struct nh_notifier_single_info *nh_obj, int weight)
 5114{
 5115	struct net_device *dev = nh_obj->dev;
 5116	int err;
 5117
 5118	nh->nhgi = nh_grp->nhgi;
 5119	nh->nh_weight = weight;
 5120
 5121	switch (nh_obj->gw_family) {
 5122	case AF_INET:
 5123		memcpy(&nh->gw_addr, &nh_obj->ipv4, sizeof(nh_obj->ipv4));
 5124		nh->neigh_tbl = &arp_tbl;
 5125		break;
 5126	case AF_INET6:
 5127		memcpy(&nh->gw_addr, &nh_obj->ipv6, sizeof(nh_obj->ipv6));
 5128#if IS_ENABLED(CONFIG_IPV6)
 5129		nh->neigh_tbl = &nd_tbl;
 5130#endif
 5131		break;
 5132	}
 5133
 5134	list_add_tail(&nh->router_list_node, &mlxsw_sp->router->nexthop_list);
 5135	nh->ifindex = dev->ifindex;
 5136	nh->id = nh_obj->id;
 5137
 5138	err = mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
 5139	if (err)
 5140		goto err_type_init;
 5141
 5142	if (nh_obj->is_reject)
 5143		mlxsw_sp_nexthop_obj_blackhole_init(mlxsw_sp, nh);
 5144
 5145	/* In a resilient nexthop group, all the nexthops must be written to
 5146	 * the adjacency table. Even if they do not have a valid neighbour or
 5147	 * RIF.
 5148	 */
 5149	if (nh_grp->nhgi->is_resilient && !nh->should_offload) {
 5150		nh->action = MLXSW_SP_NEXTHOP_ACTION_TRAP;
 5151		nh->should_offload = 1;
 5152	}
 5153
 5154	return 0;
 5155
 5156err_type_init:
 5157	list_del(&nh->router_list_node);
 5158	return err;
 5159}
 5160
 5161static void mlxsw_sp_nexthop_obj_fini(struct mlxsw_sp *mlxsw_sp,
 5162				      struct mlxsw_sp_nexthop *nh)
 5163{
 5164	if (nh->action == MLXSW_SP_NEXTHOP_ACTION_DISCARD)
 5165		mlxsw_sp_nexthop_obj_blackhole_fini(mlxsw_sp, nh);
 5166	mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
 5167	list_del(&nh->router_list_node);
 5168	mlxsw_sp_nexthop_counter_disable(mlxsw_sp, nh);
 5169	nh->should_offload = 0;
 5170}
 5171
 5172static int
 5173mlxsw_sp_nexthop_obj_group_info_init(struct mlxsw_sp *mlxsw_sp,
 5174				     struct mlxsw_sp_nexthop_group *nh_grp,
 5175				     struct nh_notifier_info *info)
 5176{
 5177	struct mlxsw_sp_nexthop_group_info *nhgi;
 5178	struct mlxsw_sp_nexthop *nh;
 5179	bool is_resilient = false;
 5180	bool hw_stats = false;
 5181	unsigned int nhs;
 5182	int err, i;
 5183
 5184	switch (info->type) {
 5185	case NH_NOTIFIER_INFO_TYPE_SINGLE:
 5186		nhs = 1;
 5187		break;
 5188	case NH_NOTIFIER_INFO_TYPE_GRP:
 5189		nhs = info->nh_grp->num_nh;
 5190		hw_stats = info->nh_grp->hw_stats;
 5191		break;
 5192	case NH_NOTIFIER_INFO_TYPE_RES_TABLE:
 5193		nhs = info->nh_res_table->num_nh_buckets;
 5194		hw_stats = info->nh_res_table->hw_stats;
 5195		is_resilient = true;
 5196		break;
 5197	default:
 5198		return -EINVAL;
 5199	}
 5200
 5201	nhgi = kzalloc(struct_size(nhgi, nexthops, nhs), GFP_KERNEL);
 5202	if (!nhgi)
 5203		return -ENOMEM;
 5204	nh_grp->nhgi = nhgi;
 5205	nhgi->nh_grp = nh_grp;
 5206	nhgi->gateway = mlxsw_sp_nexthop_obj_is_gateway(mlxsw_sp, info);
 5207	nhgi->is_resilient = is_resilient;
 5208	nhgi->count = nhs;
 5209	nhgi->hw_stats = hw_stats;
 5210
 5211	xa_init_flags(&nhgi->nexthop_counters, XA_FLAGS_ALLOC1);
 5212
 5213	for (i = 0; i < nhgi->count; i++) {
 5214		struct nh_notifier_single_info *nh_obj;
 5215		int weight;
 5216
 5217		nh = &nhgi->nexthops[i];
 5218		switch (info->type) {
 5219		case NH_NOTIFIER_INFO_TYPE_SINGLE:
 5220			nh_obj = info->nh;
 5221			weight = 1;
 5222			break;
 5223		case NH_NOTIFIER_INFO_TYPE_GRP:
 5224			nh_obj = &info->nh_grp->nh_entries[i].nh;
 5225			weight = info->nh_grp->nh_entries[i].weight;
 5226			break;
 5227		case NH_NOTIFIER_INFO_TYPE_RES_TABLE:
 5228			nh_obj = &info->nh_res_table->nhs[i];
 5229			weight = 1;
 5230			break;
 5231		default:
 5232			err = -EINVAL;
 5233			goto err_nexthop_obj_init;
 5234		}
 5235		err = mlxsw_sp_nexthop_obj_init(mlxsw_sp, nh_grp, nh, nh_obj,
 5236						weight);
 5237		if (err)
 5238			goto err_nexthop_obj_init;
 5239	}
 5240	err = mlxsw_sp_nexthop_group_inc(mlxsw_sp);
 5241	if (err)
 5242		goto err_group_inc;
 5243	err = mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
 5244	if (err) {
 5245		NL_SET_ERR_MSG_MOD(info->extack, "Failed to write adjacency entries to the device");
 5246		goto err_group_refresh;
 5247	}
 5248
 5249	/* Add resilient nexthop groups to a list so that the activity of their
 5250	 * nexthop buckets will be periodically queried and cleared.
 5251	 */
 5252	if (nhgi->is_resilient) {
 5253		if (list_empty(&mlxsw_sp->router->nh_res_grp_list))
 5254			mlxsw_sp_nh_grp_activity_work_schedule(mlxsw_sp);
 5255		list_add(&nhgi->list, &mlxsw_sp->router->nh_res_grp_list);
 5256	}
 5257
 5258	return 0;
 5259
 5260err_group_refresh:
 5261	mlxsw_sp_nexthop_group_dec(mlxsw_sp);
 5262err_group_inc:
 5263	i = nhgi->count;
 5264err_nexthop_obj_init:
 5265	for (i--; i >= 0; i--) {
 5266		nh = &nhgi->nexthops[i];
 5267		mlxsw_sp_nexthop_obj_fini(mlxsw_sp, nh);
 5268	}
 5269	kfree(nhgi);
 5270	return err;
 5271}
 5272
 5273static void
 5274mlxsw_sp_nexthop_obj_group_info_fini(struct mlxsw_sp *mlxsw_sp,
 5275				     struct mlxsw_sp_nexthop_group *nh_grp)
 5276{
 5277	struct mlxsw_sp_nexthop_group_info *nhgi = nh_grp->nhgi;
 5278	struct mlxsw_sp_router *router = mlxsw_sp->router;
 5279	int i;
 5280
 5281	if (nhgi->is_resilient) {
 5282		list_del(&nhgi->list);
 5283		if (list_empty(&mlxsw_sp->router->nh_res_grp_list))
 5284			cancel_delayed_work(&router->nh_grp_activity_dw);
 5285	}
 5286
 5287	mlxsw_sp_nexthop_group_dec(mlxsw_sp);
 5288	for (i = nhgi->count - 1; i >= 0; i--) {
 5289		struct mlxsw_sp_nexthop *nh = &nhgi->nexthops[i];
 5290
 5291		mlxsw_sp_nexthop_obj_fini(mlxsw_sp, nh);
 5292	}
 5293	mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
 5294	WARN_ON_ONCE(nhgi->adj_index_valid);
 5295	WARN_ON(!xa_empty(&nhgi->nexthop_counters));
 5296	xa_destroy(&nhgi->nexthop_counters);
 5297	kfree(nhgi);
 5298}
 5299
 5300static struct mlxsw_sp_nexthop_group *
 5301mlxsw_sp_nexthop_obj_group_create(struct mlxsw_sp *mlxsw_sp,
 5302				  struct nh_notifier_info *info)
 5303{
 5304	struct mlxsw_sp_nexthop_group *nh_grp;
 5305	int err;
 5306
 5307	nh_grp = kzalloc(sizeof(*nh_grp), GFP_KERNEL);
 5308	if (!nh_grp)
 5309		return ERR_PTR(-ENOMEM);
 5310	INIT_LIST_HEAD(&nh_grp->vr_list);
 5311	err = rhashtable_init(&nh_grp->vr_ht,
 5312			      &mlxsw_sp_nexthop_group_vr_ht_params);
 5313	if (err)
 5314		goto err_nexthop_group_vr_ht_init;
 5315	INIT_LIST_HEAD(&nh_grp->fib_list);
 5316	nh_grp->type = MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ;
 5317	nh_grp->obj.id = info->id;
 5318
 5319	err = mlxsw_sp_nexthop_obj_group_info_init(mlxsw_sp, nh_grp, info);
 5320	if (err)
 5321		goto err_nexthop_group_info_init;
 5322
 5323	nh_grp->can_destroy = false;
 5324
 5325	return nh_grp;
 5326
 5327err_nexthop_group_info_init:
 5328	rhashtable_destroy(&nh_grp->vr_ht);
 5329err_nexthop_group_vr_ht_init:
 5330	kfree(nh_grp);
 5331	return ERR_PTR(err);
 5332}
 5333
 5334static void
 5335mlxsw_sp_nexthop_obj_group_destroy(struct mlxsw_sp *mlxsw_sp,
 5336				   struct mlxsw_sp_nexthop_group *nh_grp)
 5337{
 5338	if (!nh_grp->can_destroy)
 5339		return;
 5340	mlxsw_sp_nexthop_obj_group_info_fini(mlxsw_sp, nh_grp);
 5341	WARN_ON_ONCE(!list_empty(&nh_grp->fib_list));
 5342	WARN_ON_ONCE(!list_empty(&nh_grp->vr_list));
 5343	rhashtable_destroy(&nh_grp->vr_ht);
 5344	kfree(nh_grp);
 5345}
 5346
 5347static struct mlxsw_sp_nexthop_group *
 5348mlxsw_sp_nexthop_obj_group_lookup(struct mlxsw_sp *mlxsw_sp, u32 id)
 5349{
 5350	struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg;
 5351
 5352	cmp_arg.type = MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ;
 5353	cmp_arg.id = id;
 5354	return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_group_ht,
 5355				      &cmp_arg,
 5356				      mlxsw_sp_nexthop_group_ht_params);
 5357}
 5358
 5359static int mlxsw_sp_nexthop_obj_group_add(struct mlxsw_sp *mlxsw_sp,
 5360					  struct mlxsw_sp_nexthop_group *nh_grp)
 5361{
 5362	return mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
 5363}
 5364
 5365static int
 5366mlxsw_sp_nexthop_obj_group_replace(struct mlxsw_sp *mlxsw_sp,
 5367				   struct mlxsw_sp_nexthop_group *nh_grp,
 5368				   struct mlxsw_sp_nexthop_group *old_nh_grp,
 5369				   struct netlink_ext_ack *extack)
 5370{
 5371	struct mlxsw_sp_nexthop_group_info *old_nhgi = old_nh_grp->nhgi;
 5372	struct mlxsw_sp_nexthop_group_info *new_nhgi = nh_grp->nhgi;
 5373	int err;
 5374
 5375	old_nh_grp->nhgi = new_nhgi;
 5376	new_nhgi->nh_grp = old_nh_grp;
 5377	nh_grp->nhgi = old_nhgi;
 5378	old_nhgi->nh_grp = nh_grp;
 5379
 5380	if (old_nhgi->adj_index_valid && new_nhgi->adj_index_valid) {
 5381		/* Both the old adjacency index and the new one are valid.
 5382		 * Routes are currently using the old one. Tell the device to
 5383		 * replace the old adjacency index with the new one.
 5384		 */
 5385		err = mlxsw_sp_adj_index_mass_update(mlxsw_sp, old_nh_grp,
 5386						     old_nhgi->adj_index,
 5387						     old_nhgi->ecmp_size);
 5388		if (err) {
 5389			NL_SET_ERR_MSG_MOD(extack, "Failed to replace old adjacency index with new one");
 5390			goto err_out;
 5391		}
 5392	} else if (old_nhgi->adj_index_valid && !new_nhgi->adj_index_valid) {
 5393		/* The old adjacency index is valid, while the new one is not.
 5394		 * Iterate over all the routes using the group and change them
 5395		 * to trap packets to the CPU.
 5396		 */
 5397		err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, old_nh_grp);
 5398		if (err) {
 5399			NL_SET_ERR_MSG_MOD(extack, "Failed to update routes to trap packets");
 5400			goto err_out;
 5401		}
 5402	} else if (!old_nhgi->adj_index_valid && new_nhgi->adj_index_valid) {
 5403		/* The old adjacency index is invalid, while the new one is.
 5404		 * Iterate over all the routes using the group and change them
 5405		 * to forward packets using the new valid index.
 5406		 */
 5407		err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, old_nh_grp);
 5408		if (err) {
 5409			NL_SET_ERR_MSG_MOD(extack, "Failed to update routes to forward packets");
 5410			goto err_out;
 5411		}
 5412	}
 5413
 5414	/* Make sure the flags are set / cleared based on the new nexthop group
 5415	 * information.
 5416	 */
 5417	mlxsw_sp_nexthop_obj_group_offload_refresh(mlxsw_sp, old_nh_grp);
 5418
 5419	/* At this point 'nh_grp' is just a shell that is not used by anyone
 5420	 * and its nexthop group info is the old info that was just replaced
 5421	 * with the new one. Remove it.
 5422	 */
 5423	nh_grp->can_destroy = true;
 5424	mlxsw_sp_nexthop_obj_group_destroy(mlxsw_sp, nh_grp);
 5425
 5426	return 0;
 5427
 5428err_out:
 5429	old_nhgi->nh_grp = old_nh_grp;
 5430	nh_grp->nhgi = new_nhgi;
 5431	new_nhgi->nh_grp = nh_grp;
 5432	old_nh_grp->nhgi = old_nhgi;
 5433	return err;
 5434}
 5435
 5436static int mlxsw_sp_nexthop_obj_res_group_pre(struct mlxsw_sp *mlxsw_sp,
 5437					      struct nh_notifier_info *info)
 5438{
 5439	struct nh_notifier_grp_info *grp_info = info->nh_grp;
 5440	struct mlxsw_sp_nexthop_group_info *nhgi;
 5441	struct mlxsw_sp_nexthop_group *nh_grp;
 5442	int err;
 5443	int i;
 5444
 5445	nh_grp = mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, info->id);
 5446	if (!nh_grp)
 5447		return 0;
 5448	nhgi = nh_grp->nhgi;
 5449
 5450	if (nhgi->hw_stats == grp_info->hw_stats)
 5451		return 0;
 5452
 5453	nhgi->hw_stats = grp_info->hw_stats;
 5454
 5455	for (i = 0; i < nhgi->count; i++) {
 5456		struct mlxsw_sp_nexthop *nh = &nhgi->nexthops[i];
 5457
 5458		if (nh->offloaded)
 5459			nh->update = 1;
 5460	}
 5461
 5462	err = mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
 5463	if (err)
 5464		goto err_group_refresh;
 5465
 5466	return 0;
 5467
 5468err_group_refresh:
 5469	nhgi->hw_stats = !grp_info->hw_stats;
 5470	return err;
 5471}
 5472
 5473static int mlxsw_sp_nexthop_obj_new(struct mlxsw_sp *mlxsw_sp,
 5474				    struct nh_notifier_info *info)
 5475{
 5476	struct mlxsw_sp_nexthop_group *nh_grp, *old_nh_grp;
 5477	struct netlink_ext_ack *extack = info->extack;
 5478	int err;
 5479
 5480	nh_grp = mlxsw_sp_nexthop_obj_group_create(mlxsw_sp, info);
 5481	if (IS_ERR(nh_grp))
 5482		return PTR_ERR(nh_grp);
 5483
 5484	old_nh_grp = mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, info->id);
 5485	if (!old_nh_grp)
 5486		err = mlxsw_sp_nexthop_obj_group_add(mlxsw_sp, nh_grp);
 5487	else
 5488		err = mlxsw_sp_nexthop_obj_group_replace(mlxsw_sp, nh_grp,
 5489							 old_nh_grp, extack);
 5490
 5491	if (err) {
 5492		nh_grp->can_destroy = true;
 5493		mlxsw_sp_nexthop_obj_group_destroy(mlxsw_sp, nh_grp);
 5494	}
 5495
 5496	return err;
 5497}
 5498
 5499static void mlxsw_sp_nexthop_obj_del(struct mlxsw_sp *mlxsw_sp,
 5500				     struct nh_notifier_info *info)
 5501{
 5502	struct mlxsw_sp_nexthop_group *nh_grp;
 5503
 5504	nh_grp = mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, info->id);
 5505	if (!nh_grp)
 5506		return;
 5507
 5508	nh_grp->can_destroy = true;
 5509	mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
 5510
 5511	/* If the group still has routes using it, then defer the delete
 5512	 * operation until the last route using it is deleted.
 5513	 */
 5514	if (!list_empty(&nh_grp->fib_list))
 5515		return;
 5516	mlxsw_sp_nexthop_obj_group_destroy(mlxsw_sp, nh_grp);
 5517}
 5518
 5519static int mlxsw_sp_nexthop_obj_bucket_query(struct mlxsw_sp *mlxsw_sp,
 5520					     u32 adj_index, char *ratr_pl)
 5521{
 5522	MLXSW_REG_ZERO(ratr, ratr_pl);
 5523	mlxsw_reg_ratr_op_set(ratr_pl, MLXSW_REG_RATR_OP_QUERY_READ);
 5524	mlxsw_reg_ratr_adjacency_index_low_set(ratr_pl, adj_index);
 5525	mlxsw_reg_ratr_adjacency_index_high_set(ratr_pl, adj_index >> 16);
 5526
 5527	return mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
 5528}
 5529
 5530static int mlxsw_sp_nexthop_obj_bucket_compare(char *ratr_pl, char *ratr_pl_new)
 5531{
 5532	/* Clear the opcode and activity on both the old and new payload as
 5533	 * they are irrelevant for the comparison.
 5534	 */
 5535	mlxsw_reg_ratr_op_set(ratr_pl, MLXSW_REG_RATR_OP_QUERY_READ);
 5536	mlxsw_reg_ratr_a_set(ratr_pl, 0);
 5537	mlxsw_reg_ratr_op_set(ratr_pl_new, MLXSW_REG_RATR_OP_QUERY_READ);
 5538	mlxsw_reg_ratr_a_set(ratr_pl_new, 0);
 5539
 5540	/* If the contents of the adjacency entry are consistent with the
 5541	 * replacement request, then replacement was successful.
 5542	 */
 5543	if (!memcmp(ratr_pl, ratr_pl_new, MLXSW_REG_RATR_LEN))
 5544		return 0;
 5545
 5546	return -EINVAL;
 5547}
 5548
 5549static int
 5550mlxsw_sp_nexthop_obj_bucket_adj_update(struct mlxsw_sp *mlxsw_sp,
 5551				       struct mlxsw_sp_nexthop *nh,
 5552				       struct nh_notifier_info *info)
 5553{
 5554	u16 bucket_index = info->nh_res_bucket->bucket_index;
 5555	struct netlink_ext_ack *extack = info->extack;
 5556	bool force = info->nh_res_bucket->force;
 5557	char ratr_pl_new[MLXSW_REG_RATR_LEN];
 5558	char ratr_pl[MLXSW_REG_RATR_LEN];
 5559	u32 adj_index;
 5560	int err;
 5561
 5562	/* No point in trying an atomic replacement if the idle timer interval
 5563	 * is smaller than the interval in which we query and clear activity.
 5564	 */
 5565	if (!force && info->nh_res_bucket->idle_timer_ms <
 5566	    MLXSW_SP_NH_GRP_ACTIVITY_UPDATE_INTERVAL)
 5567		force = true;
 5568
 5569	adj_index = nh->nhgi->adj_index + bucket_index;
 5570	err = mlxsw_sp_nexthop_update(mlxsw_sp, adj_index, nh, force, ratr_pl);
 5571	if (err) {
 5572		NL_SET_ERR_MSG_MOD(extack, "Failed to overwrite nexthop bucket");
 5573		return err;
 5574	}
 5575
 5576	if (!force) {
 5577		err = mlxsw_sp_nexthop_obj_bucket_query(mlxsw_sp, adj_index,
 5578							ratr_pl_new);
 5579		if (err) {
 5580			NL_SET_ERR_MSG_MOD(extack, "Failed to query nexthop bucket state after replacement. State might be inconsistent");
 5581			return err;
 5582		}
 5583
 5584		err = mlxsw_sp_nexthop_obj_bucket_compare(ratr_pl, ratr_pl_new);
 5585		if (err) {
 5586			NL_SET_ERR_MSG_MOD(extack, "Nexthop bucket was not replaced because it was active during replacement");
 5587			return err;
 5588		}
 5589	}
 5590
 5591	nh->update = 0;
 5592	nh->offloaded = 1;
 5593	mlxsw_sp_nexthop_bucket_offload_refresh(mlxsw_sp, nh, bucket_index);
 5594
 5595	return 0;
 5596}
 5597
 5598static int mlxsw_sp_nexthop_obj_bucket_replace(struct mlxsw_sp *mlxsw_sp,
 5599					       struct nh_notifier_info *info)
 5600{
 5601	u16 bucket_index = info->nh_res_bucket->bucket_index;
 5602	struct netlink_ext_ack *extack = info->extack;
 5603	struct mlxsw_sp_nexthop_group_info *nhgi;
 5604	struct nh_notifier_single_info *nh_obj;
 5605	struct mlxsw_sp_nexthop_group *nh_grp;
 5606	struct mlxsw_sp_nexthop *nh;
 5607	int err;
 5608
 5609	nh_grp = mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, info->id);
 5610	if (!nh_grp) {
 5611		NL_SET_ERR_MSG_MOD(extack, "Nexthop group was not found");
 5612		return -EINVAL;
 5613	}
 5614
 5615	nhgi = nh_grp->nhgi;
 5616
 5617	if (bucket_index >= nhgi->count) {
 5618		NL_SET_ERR_MSG_MOD(extack, "Nexthop bucket index out of range");
 5619		return -EINVAL;
 5620	}
 5621
 5622	nh = &nhgi->nexthops[bucket_index];
 5623	mlxsw_sp_nexthop_obj_fini(mlxsw_sp, nh);
 5624
 5625	nh_obj = &info->nh_res_bucket->new_nh;
 5626	err = mlxsw_sp_nexthop_obj_init(mlxsw_sp, nh_grp, nh, nh_obj, 1);
 5627	if (err) {
 5628		NL_SET_ERR_MSG_MOD(extack, "Failed to initialize nexthop object for nexthop bucket replacement");
 5629		goto err_nexthop_obj_init;
 5630	}
 5631
 5632	err = mlxsw_sp_nexthop_obj_bucket_adj_update(mlxsw_sp, nh, info);
 5633	if (err)
 5634		goto err_nexthop_obj_bucket_adj_update;
 5635
 5636	return 0;
 5637
 5638err_nexthop_obj_bucket_adj_update:
 5639	mlxsw_sp_nexthop_obj_fini(mlxsw_sp, nh);
 5640err_nexthop_obj_init:
 5641	nh_obj = &info->nh_res_bucket->old_nh;
 5642	mlxsw_sp_nexthop_obj_init(mlxsw_sp, nh_grp, nh, nh_obj, 1);
 5643	/* The old adjacency entry was not overwritten */
 5644	nh->update = 0;
 5645	nh->offloaded = 1;
 5646	return err;
 5647}
 5648
 5649static void
 5650mlxsw_sp_nexthop_obj_mp_hw_stats_get(struct mlxsw_sp *mlxsw_sp,
 5651				     struct mlxsw_sp_nexthop_group_info *nhgi,
 5652				     struct nh_notifier_grp_hw_stats_info *info)
 5653{
 5654	int nhi;
 5655
 5656	for (nhi = 0; nhi < info->num_nh; nhi++) {
 5657		struct mlxsw_sp_nexthop *nh = &nhgi->nexthops[nhi];
 5658		u64 packets;
 5659		int err;
 5660
 5661		err = mlxsw_sp_nexthop_counter_get(mlxsw_sp, nh, &packets);
 5662		if (err)
 5663			continue;
 5664
 5665		nh_grp_hw_stats_report_delta(info, nhi, packets);
 5666	}
 5667}
 5668
 5669static void
 5670mlxsw_sp_nexthop_obj_res_hw_stats_get(struct mlxsw_sp *mlxsw_sp,
 5671				      struct mlxsw_sp_nexthop_group_info *nhgi,
 5672				      struct nh_notifier_grp_hw_stats_info *info)
 5673{
 5674	int nhi = -1;
 5675	int bucket;
 5676
 5677	for (bucket = 0; bucket < nhgi->count; bucket++) {
 5678		struct mlxsw_sp_nexthop *nh = &nhgi->nexthops[bucket];
 5679		u64 packets;
 5680		int err;
 5681
 5682		if (nhi == -1 || info->stats[nhi].id != nh->id) {
 5683			for (nhi = 0; nhi < info->num_nh; nhi++)
 5684				if (info->stats[nhi].id == nh->id)
 5685					break;
 5686			if (WARN_ON_ONCE(nhi == info->num_nh)) {
 5687				nhi = -1;
 5688				continue;
 5689			}
 5690		}
 5691
 5692		err = mlxsw_sp_nexthop_counter_get(mlxsw_sp, nh, &packets);
 5693		if (err)
 5694			continue;
 5695
 5696		nh_grp_hw_stats_report_delta(info, nhi, packets);
 5697	}
 5698}
 5699
 5700static void mlxsw_sp_nexthop_obj_hw_stats_get(struct mlxsw_sp *mlxsw_sp,
 5701					      struct nh_notifier_info *info)
 5702{
 5703	struct mlxsw_sp_nexthop_group_info *nhgi;
 5704	struct mlxsw_sp_nexthop_group *nh_grp;
 5705
 5706	if (info->type != NH_NOTIFIER_INFO_TYPE_GRP_HW_STATS)
 5707		return;
 5708
 5709	nh_grp = mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, info->id);
 5710	if (!nh_grp)
 5711		return;
 5712	nhgi = nh_grp->nhgi;
 5713
 5714	if (nhgi->is_resilient)
 5715		mlxsw_sp_nexthop_obj_res_hw_stats_get(mlxsw_sp, nhgi,
 5716						      info->nh_grp_hw_stats);
 5717	else
 5718		mlxsw_sp_nexthop_obj_mp_hw_stats_get(mlxsw_sp, nhgi,
 5719						     info->nh_grp_hw_stats);
 5720}
 5721
 5722static int mlxsw_sp_nexthop_obj_event(struct notifier_block *nb,
 5723				      unsigned long event, void *ptr)
 5724{
 5725	struct nh_notifier_info *info = ptr;
 5726	struct mlxsw_sp_router *router;
 5727	int err = 0;
 5728
 5729	router = container_of(nb, struct mlxsw_sp_router, nexthop_nb);
 5730	err = mlxsw_sp_nexthop_obj_validate(router->mlxsw_sp, event, info);
 5731	if (err)
 5732		goto out;
 5733
 5734	mutex_lock(&router->lock);
 5735
 5736	switch (event) {
 5737	case NEXTHOP_EVENT_RES_TABLE_PRE_REPLACE:
 5738		err = mlxsw_sp_nexthop_obj_res_group_pre(router->mlxsw_sp,
 5739							 info);
 5740		break;
 5741	case NEXTHOP_EVENT_REPLACE:
 5742		err = mlxsw_sp_nexthop_obj_new(router->mlxsw_sp, info);
 5743		break;
 5744	case NEXTHOP_EVENT_DEL:
 5745		mlxsw_sp_nexthop_obj_del(router->mlxsw_sp, info);
 5746		break;
 5747	case NEXTHOP_EVENT_BUCKET_REPLACE:
 5748		err = mlxsw_sp_nexthop_obj_bucket_replace(router->mlxsw_sp,
 5749							  info);
 5750		break;
 5751	case NEXTHOP_EVENT_HW_STATS_REPORT_DELTA:
 5752		mlxsw_sp_nexthop_obj_hw_stats_get(router->mlxsw_sp, info);
 5753		break;
 5754	default:
 5755		break;
 5756	}
 5757
 5758	mutex_unlock(&router->lock);
 5759
 5760out:
 5761	return notifier_from_errno(err);
 5762}
 5763
 5764static bool mlxsw_sp_fi_is_gateway(const struct mlxsw_sp *mlxsw_sp,
 5765				   struct fib_info *fi)
 5766{
 5767	const struct fib_nh *nh = fib_info_nh(fi, 0);
 5768
 5769	return nh->fib_nh_gw_family ||
 5770	       mlxsw_sp_nexthop4_ipip_type(mlxsw_sp, nh, NULL);
 5771}
 5772
 5773static int
 5774mlxsw_sp_nexthop4_group_info_init(struct mlxsw_sp *mlxsw_sp,
 5775				  struct mlxsw_sp_nexthop_group *nh_grp)
 5776{
 5777	unsigned int nhs = fib_info_num_path(nh_grp->ipv4.fi);
 5778	struct mlxsw_sp_nexthop_group_info *nhgi;
 5779	struct mlxsw_sp_nexthop *nh;
 5780	int err, i;
 5781
 5782	nhgi = kzalloc(struct_size(nhgi, nexthops, nhs), GFP_KERNEL);
 5783	if (!nhgi)
 5784		return -ENOMEM;
 5785	nh_grp->nhgi = nhgi;
 5786	nhgi->nh_grp = nh_grp;
 5787	nhgi->gateway = mlxsw_sp_fi_is_gateway(mlxsw_sp, nh_grp->ipv4.fi);
 5788	nhgi->count = nhs;
 5789	for (i = 0; i < nhgi->count; i++) {
 5790		struct fib_nh *fib_nh;
 5791
 5792		nh = &nhgi->nexthops[i];
 5793		fib_nh = fib_info_nh(nh_grp->ipv4.fi, i);
 5794		err = mlxsw_sp_nexthop4_init(mlxsw_sp, nh_grp, nh, fib_nh);
 5795		if (err)
 5796			goto err_nexthop4_init;
 5797	}
 5798	err = mlxsw_sp_nexthop_group_inc(mlxsw_sp);
 5799	if (err)
 5800		goto err_group_inc;
 5801	err = mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
 5802	if (err)
 5803		goto err_group_refresh;
 5804
 5805	return 0;
 5806
 5807err_group_refresh:
 5808	mlxsw_sp_nexthop_group_dec(mlxsw_sp);
 5809err_group_inc:
 5810	i = nhgi->count;
 5811err_nexthop4_init:
 5812	for (i--; i >= 0; i--) {
 5813		nh = &nhgi->nexthops[i];
 5814		mlxsw_sp_nexthop4_fini(mlxsw_sp, nh);
 5815	}
 5816	kfree(nhgi);
 5817	return err;
 5818}
 5819
 5820static void
 5821mlxsw_sp_nexthop4_group_info_fini(struct mlxsw_sp *mlxsw_sp,
 5822				  struct mlxsw_sp_nexthop_group *nh_grp)
 5823{
 5824	struct mlxsw_sp_nexthop_group_info *nhgi = nh_grp->nhgi;
 5825	int i;
 5826
 5827	mlxsw_sp_nexthop_group_dec(mlxsw_sp);
 5828	for (i = nhgi->count - 1; i >= 0; i--) {
 5829		struct mlxsw_sp_nexthop *nh = &nhgi->nexthops[i];
 5830
 5831		mlxsw_sp_nexthop4_fini(mlxsw_sp, nh);
 5832	}
 5833	mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
 5834	WARN_ON_ONCE(nhgi->adj_index_valid);
 5835	kfree(nhgi);
 5836}
 5837
 5838static struct mlxsw_sp_nexthop_group *
 5839mlxsw_sp_nexthop4_group_create(struct mlxsw_sp *mlxsw_sp, struct fib_info *fi)
 5840{
 5841	struct mlxsw_sp_nexthop_group *nh_grp;
 5842	int err;
 5843
 5844	nh_grp = kzalloc(sizeof(*nh_grp), GFP_KERNEL);
 5845	if (!nh_grp)
 5846		return ERR_PTR(-ENOMEM);
 5847	INIT_LIST_HEAD(&nh_grp->vr_list);
 5848	err = rhashtable_init(&nh_grp->vr_ht,
 5849			      &mlxsw_sp_nexthop_group_vr_ht_params);
 5850	if (err)
 5851		goto err_nexthop_group_vr_ht_init;
 5852	INIT_LIST_HEAD(&nh_grp->fib_list);
 5853	nh_grp->type = MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4;
 5854	nh_grp->ipv4.fi = fi;
 5855	fib_info_hold(fi);
 5856
 5857	err = mlxsw_sp_nexthop4_group_info_init(mlxsw_sp, nh_grp);
 5858	if (err)
 5859		goto err_nexthop_group_info_init;
 5860
 5861	err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
 5862	if (err)
 5863		goto err_nexthop_group_insert;
 5864
 5865	nh_grp->can_destroy = true;
 5866
 5867	return nh_grp;
 5868
 5869err_nexthop_group_insert:
 5870	mlxsw_sp_nexthop4_group_info_fini(mlxsw_sp, nh_grp);
 5871err_nexthop_group_info_init:
 5872	fib_info_put(fi);
 5873	rhashtable_destroy(&nh_grp->vr_ht);
 5874err_nexthop_group_vr_ht_init:
 5875	kfree(nh_grp);
 5876	return ERR_PTR(err);
 5877}
 5878
 5879static void
 5880mlxsw_sp_nexthop4_group_destroy(struct mlxsw_sp *mlxsw_sp,
 5881				struct mlxsw_sp_nexthop_group *nh_grp)
 5882{
 5883	if (!nh_grp->can_destroy)
 5884		return;
 5885	mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
 5886	mlxsw_sp_nexthop4_group_info_fini(mlxsw_sp, nh_grp);
 5887	fib_info_put(nh_grp->ipv4.fi);
 5888	WARN_ON_ONCE(!list_empty(&nh_grp->vr_list));
 5889	rhashtable_destroy(&nh_grp->vr_ht);
 5890	kfree(nh_grp);
 5891}
 5892
 5893static int mlxsw_sp_nexthop4_group_get(struct mlxsw_sp *mlxsw_sp,
 5894				       struct mlxsw_sp_fib_entry *fib_entry,
 5895				       struct fib_info *fi)
 5896{
 5897	struct mlxsw_sp_nexthop_group *nh_grp;
 5898
 5899	if (fi->nh) {
 5900		nh_grp = mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp,
 5901							   fi->nh->id);
 5902		if (WARN_ON_ONCE(!nh_grp))
 5903			return -EINVAL;
 5904		goto out;
 5905	}
 5906
 5907	nh_grp = mlxsw_sp_nexthop4_group_lookup(mlxsw_sp, fi);
 5908	if (!nh_grp) {
 5909		nh_grp = mlxsw_sp_nexthop4_group_create(mlxsw_sp, fi);
 5910		if (IS_ERR(nh_grp))
 5911			return PTR_ERR(nh_grp);
 5912	}
 5913out:
 5914	list_add_tail(&fib_entry->nexthop_group_node, &nh_grp->fib_list);
 5915	fib_entry->nh_group = nh_grp;
 5916	return 0;
 5917}
 5918
 5919static void mlxsw_sp_nexthop4_group_put(struct mlxsw_sp *mlxsw_sp,
 5920					struct mlxsw_sp_fib_entry *fib_entry)
 5921{
 5922	struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
 5923
 5924	list_del(&fib_entry->nexthop_group_node);
 5925	if (!list_empty(&nh_grp->fib_list))
 5926		return;
 5927
 5928	if (nh_grp->type == MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ) {
 5929		mlxsw_sp_nexthop_obj_group_destroy(mlxsw_sp, nh_grp);
 5930		return;
 5931	}
 5932
 5933	mlxsw_sp_nexthop4_group_destroy(mlxsw_sp, nh_grp);
 5934}
 5935
 5936static bool
 5937mlxsw_sp_fib4_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
 5938{
 5939	struct mlxsw_sp_fib4_entry *fib4_entry;
 5940
 5941	fib4_entry = container_of(fib_entry, struct mlxsw_sp_fib4_entry,
 5942				  common);
 5943	return !fib4_entry->dscp;
 5944}
 5945
 5946static bool
 5947mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
 5948{
 5949	struct mlxsw_sp_nexthop_group *nh_group = fib_entry->nh_group;
 5950
 5951	switch (fib_entry->fib_node->fib->proto) {
 5952	case MLXSW_SP_L3_PROTO_IPV4:
 5953		if (!mlxsw_sp_fib4_entry_should_offload(fib_entry))
 5954			return false;
 5955		break;
 5956	case MLXSW_SP_L3_PROTO_IPV6:
 5957		break;
 5958	}
 5959
 5960	switch (fib_entry->type) {
 5961	case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
 5962		return !!nh_group->nhgi->adj_index_valid;
 5963	case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
 5964		return !!mlxsw_sp_nhgi_rif(nh_group->nhgi);
 5965	case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE:
 5966	case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
 5967	case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP:
 5968		return true;
 5969	default:
 5970		return false;
 5971	}
 5972}
 5973
 5974static struct mlxsw_sp_nexthop *
 5975mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
 5976		     const struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
 5977{
 5978	int i;
 5979
 5980	for (i = 0; i < nh_grp->nhgi->count; i++) {
 5981		struct mlxsw_sp_nexthop *nh = &nh_grp->nhgi->nexthops[i];
 5982		struct net_device *dev = mlxsw_sp_nexthop_dev(nh);
 5983		struct fib6_info *rt = mlxsw_sp_rt6->rt;
 5984
 5985		if (dev && dev == rt->fib6_nh->fib_nh_dev &&
 5986		    ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr,
 5987				    &rt->fib6_nh->fib_nh_gw6))
 5988			return nh;
 5989	}
 5990
 5991	return NULL;
 5992}
 5993
 5994static void
 5995mlxsw_sp_fib4_offload_failed_flag_set(struct mlxsw_sp *mlxsw_sp,
 5996				      struct fib_entry_notifier_info *fen_info)
 5997{
 5998	u32 *p_dst = (u32 *) &fen_info->dst;
 5999	struct fib_rt_info fri;
 6000
 6001	fri.fi = fen_info->fi;
 6002	fri.tb_id = fen_info->tb_id;
 6003	fri.dst = cpu_to_be32(*p_dst);
 6004	fri.dst_len = fen_info->dst_len;
 6005	fri.dscp = fen_info->dscp;
 6006	fri.type = fen_info->type;
 6007	fri.offload = false;
 6008	fri.trap = false;
 6009	fri.offload_failed = true;
 6010	fib_alias_hw_flags_set(mlxsw_sp_net(mlxsw_sp), &fri);
 6011}
 6012
 6013static void
 6014mlxsw_sp_fib4_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
 6015				 struct mlxsw_sp_fib_entry *fib_entry)
 6016{
 6017	u32 *p_dst = (u32 *) fib_entry->fib_node->key.addr;
 6018	int dst_len = fib_entry->fib_node->key.prefix_len;
 6019	struct mlxsw_sp_fib4_entry *fib4_entry;
 6020	struct fib_rt_info fri;
 6021	bool should_offload;
 6022
 6023	should_offload = mlxsw_sp_fib_entry_should_offload(fib_entry);
 6024	fib4_entry = container_of(fib_entry, struct mlxsw_sp_fib4_entry,
 6025				  common);
 6026	fri.fi = fib4_entry->fi;
 6027	fri.tb_id = fib4_entry->tb_id;
 6028	fri.dst = cpu_to_be32(*p_dst);
 6029	fri.dst_len = dst_len;
 6030	fri.dscp = fib4_entry->dscp;
 6031	fri.type = fib4_entry->type;
 6032	fri.offload = should_offload;
 6033	fri.trap = !should_offload;
 6034	fri.offload_failed = false;
 6035	fib_alias_hw_flags_set(mlxsw_sp_net(mlxsw_sp), &fri);
 6036}
 6037
 6038static void
 6039mlxsw_sp_fib4_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp,
 6040				   struct mlxsw_sp_fib_entry *fib_entry)
 6041{
 6042	u32 *p_dst = (u32 *) fib_entry->fib_node->key.addr;
 6043	int dst_len = fib_entry->fib_node->key.prefix_len;
 6044	struct mlxsw_sp_fib4_entry *fib4_entry;
 6045	struct fib_rt_info fri;
 6046
 6047	fib4_entry = container_of(fib_entry, struct mlxsw_sp_fib4_entry,
 6048				  common);
 6049	fri.fi = fib4_entry->fi;
 6050	fri.tb_id = fib4_entry->tb_id;
 6051	fri.dst = cpu_to_be32(*p_dst);
 6052	fri.dst_len = dst_len;
 6053	fri.dscp = fib4_entry->dscp;
 6054	fri.type = fib4_entry->type;
 6055	fri.offload = false;
 6056	fri.trap = false;
 6057	fri.offload_failed = false;
 6058	fib_alias_hw_flags_set(mlxsw_sp_net(mlxsw_sp), &fri);
 6059}
 6060
 6061#if IS_ENABLED(CONFIG_IPV6)
 6062static void
 6063mlxsw_sp_fib6_offload_failed_flag_set(struct mlxsw_sp *mlxsw_sp,
 6064				      struct fib6_info **rt_arr,
 6065				      unsigned int nrt6)
 6066{
 6067	int i;
 6068
 6069	/* In IPv6 a multipath route is represented using multiple routes, so
 6070	 * we need to set the flags on all of them.
 6071	 */
 6072	for (i = 0; i < nrt6; i++)
 6073		fib6_info_hw_flags_set(mlxsw_sp_net(mlxsw_sp), rt_arr[i],
 6074				       false, false, true);
 6075}
 6076#else
 6077static void
 6078mlxsw_sp_fib6_offload_failed_flag_set(struct mlxsw_sp *mlxsw_sp,
 6079				      struct fib6_info **rt_arr,
 6080				      unsigned int nrt6)
 6081{
 6082}
 6083#endif
 6084
 6085#if IS_ENABLED(CONFIG_IPV6)
 6086static void
 6087mlxsw_sp_fib6_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
 6088				 struct mlxsw_sp_fib_entry *fib_entry)
 6089{
 6090	struct mlxsw_sp_fib6_entry *fib6_entry;
 6091	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
 6092	bool should_offload;
 6093
 6094	should_offload = mlxsw_sp_fib_entry_should_offload(fib_entry);
 6095
 6096	/* In IPv6 a multipath route is represented using multiple routes, so
 6097	 * we need to set the flags on all of them.
 6098	 */
 6099	fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry,
 6100				  common);
 6101	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list)
 6102		fib6_info_hw_flags_set(mlxsw_sp_net(mlxsw_sp), mlxsw_sp_rt6->rt,
 6103				       should_offload, !should_offload, false);
 6104}
 6105#else
 6106static void
 6107mlxsw_sp_fib6_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
 6108				 struct mlxsw_sp_fib_entry *fib_entry)
 6109{
 6110}
 6111#endif
 6112
 6113#if IS_ENABLED(CONFIG_IPV6)
 6114static void
 6115mlxsw_sp_fib6_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp,
 6116				   struct mlxsw_sp_fib_entry *fib_entry)
 6117{
 6118	struct mlxsw_sp_fib6_entry *fib6_entry;
 6119	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
 6120
 6121	fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry,
 6122				  common);
 6123	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list)
 6124		fib6_info_hw_flags_set(mlxsw_sp_net(mlxsw_sp), mlxsw_sp_rt6->rt,
 6125				       false, false, false);
 6126}
 6127#else
 6128static void
 6129mlxsw_sp_fib6_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp,
 6130				   struct mlxsw_sp_fib_entry *fib_entry)
 6131{
 6132}
 6133#endif
 6134
 6135static void
 6136mlxsw_sp_fib_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
 6137				struct mlxsw_sp_fib_entry *fib_entry)
 6138{
 6139	switch (fib_entry->fib_node->fib->proto) {
 6140	case MLXSW_SP_L3_PROTO_IPV4:
 6141		mlxsw_sp_fib4_entry_hw_flags_set(mlxsw_sp, fib_entry);
 6142		break;
 6143	case MLXSW_SP_L3_PROTO_IPV6:
 6144		mlxsw_sp_fib6_entry_hw_flags_set(mlxsw_sp, fib_entry);
 6145		break;
 6146	}
 6147}
 6148
 6149static void
 6150mlxsw_sp_fib_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp,
 6151				  struct mlxsw_sp_fib_entry *fib_entry)
 6152{
 6153	switch (fib_entry->fib_node->fib->proto) {
 6154	case MLXSW_SP_L3_PROTO_IPV4:
 6155		mlxsw_sp_fib4_entry_hw_flags_clear(mlxsw_sp, fib_entry);
 6156		break;
 6157	case MLXSW_SP_L3_PROTO_IPV6:
 6158		mlxsw_sp_fib6_entry_hw_flags_clear(mlxsw_sp, fib_entry);
 6159		break;
 6160	}
 6161}
 6162
 6163static void
 6164mlxsw_sp_fib_entry_hw_flags_refresh(struct mlxsw_sp *mlxsw_sp,
 6165				    struct mlxsw_sp_fib_entry *fib_entry,
 6166				    enum mlxsw_reg_ralue_op op)
 6167{
 6168	switch (op) {
 6169	case MLXSW_REG_RALUE_OP_WRITE_WRITE:
 6170		mlxsw_sp_fib_entry_hw_flags_set(mlxsw_sp, fib_entry);
 6171		break;
 6172	case MLXSW_REG_RALUE_OP_WRITE_DELETE:
 6173		mlxsw_sp_fib_entry_hw_flags_clear(mlxsw_sp, fib_entry);
 6174		break;
 6175	default:
 6176		break;
 6177	}
 6178}
 6179
 6180static void
 6181mlxsw_sp_fib_entry_ralue_pack(char *ralue_pl,
 6182			      const struct mlxsw_sp_fib_entry *fib_entry,
 6183			      enum mlxsw_reg_ralue_op op)
 6184{
 6185	struct mlxsw_sp_fib *fib = fib_entry->fib_node->fib;
 6186	enum mlxsw_reg_ralxx_protocol proto;
 6187	u32 *p_dip;
 6188
 6189	proto = (enum mlxsw_reg_ralxx_protocol) fib->proto;
 6190
 6191	switch (fib->proto) {
 6192	case MLXSW_SP_L3_PROTO_IPV4:
 6193		p_dip = (u32 *) fib_entry->fib_node->key.addr;
 6194		mlxsw_reg_ralue_pack4(ralue_pl, proto, op, fib->vr->id,
 6195				      fib_entry->fib_node->key.prefix_len,
 6196				      *p_dip);
 6197		break;
 6198	case MLXSW_SP_L3_PROTO_IPV6:
 6199		mlxsw_reg_ralue_pack6(ralue_pl, proto, op, fib->vr->id,
 6200				      fib_entry->fib_node->key.prefix_len,
 6201				      fib_entry->fib_node->key.addr);
 6202		break;
 6203	}
 6204}
 6205
 6206static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp,
 6207					struct mlxsw_sp_fib_entry *fib_entry,
 6208					enum mlxsw_reg_ralue_op op)
 6209{
 6210	struct mlxsw_sp_nexthop_group *nh_group = fib_entry->nh_group;
 6211	struct mlxsw_sp_nexthop_group_info *nhgi = nh_group->nhgi;
 6212	char ralue_pl[MLXSW_REG_RALUE_LEN];
 6213	enum mlxsw_reg_ralue_trap_action trap_action;
 6214	u16 trap_id = 0;
 6215	u32 adjacency_index = 0;
 6216	u16 ecmp_size = 0;
 6217
 6218	/* In case the nexthop group adjacency index is valid, use it
 6219	 * with provided ECMP size. Otherwise, setup trap and pass
 6220	 * traffic to kernel.
 6221	 */
 6222	if (mlxsw_sp_fib_entry_should_offload(fib_entry)) {
 6223		trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
 6224		adjacency_index = nhgi->adj_index;
 6225		ecmp_size = nhgi->ecmp_size;
 6226	} else if (!nhgi->adj_index_valid && nhgi->count &&
 6227		   mlxsw_sp_nhgi_rif(nhgi)) {
 6228		trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
 6229		adjacency_index = mlxsw_sp->router->adj_trap_index;
 6230		ecmp_size = 1;
 6231	} else {
 6232		trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
 6233		trap_id = MLXSW_TRAP_ID_RTR_INGRESS0;
 6234	}
 6235
 6236	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
 6237	mlxsw_reg_ralue_act_remote_pack(ralue_pl, trap_action, trap_id,
 6238					adjacency_index, ecmp_size);
 6239	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
 6240}
 6241
 6242static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp *mlxsw_sp,
 6243				       struct mlxsw_sp_fib_entry *fib_entry,
 6244				       enum mlxsw_reg_ralue_op op)
 6245{
 6246	struct mlxsw_sp_rif *rif = mlxsw_sp_nhgi_rif(fib_entry->nh_group->nhgi);
 6247	enum mlxsw_reg_ralue_trap_action trap_action;
 6248	char ralue_pl[MLXSW_REG_RALUE_LEN];
 6249	u16 trap_id = 0;
 6250	u16 rif_index = 0;
 6251
 6252	if (mlxsw_sp_fib_entry_should_offload(fib_entry)) {
 6253		trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
 6254		rif_index = rif->rif_index;
 6255	} else {
 6256		trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
 6257		trap_id = MLXSW_TRAP_ID_RTR_INGRESS0;
 6258	}
 6259
 6260	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
 6261	mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, trap_id,
 6262				       rif_index);
 6263	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
 6264}
 6265
 6266static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp *mlxsw_sp,
 6267				      struct mlxsw_sp_fib_entry *fib_entry,
 6268				      enum mlxsw_reg_ralue_op op)
 6269{
 6270	char ralue_pl[MLXSW_REG_RALUE_LEN];
 6271
 6272	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
 6273	mlxsw_reg_ralue_act_ip2me_pack(ralue_pl);
 6274	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
 6275}
 6276
 6277static int mlxsw_sp_fib_entry_op_blackhole(struct mlxsw_sp *mlxsw_sp,
 6278					   struct mlxsw_sp_fib_entry *fib_entry,
 6279					   enum mlxsw_reg_ralue_op op)
 6280{
 6281	enum mlxsw_reg_ralue_trap_action trap_action;
 6282	char ralue_pl[MLXSW_REG_RALUE_LEN];
 6283
 6284	trap_action = MLXSW_REG_RALUE_TRAP_ACTION_DISCARD_ERROR;
 6285	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
 6286	mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, 0, 0);
 6287	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
 6288}
 6289
 6290static int
 6291mlxsw_sp_fib_entry_op_unreachable(struct mlxsw_sp *mlxsw_sp,
 6292				  struct mlxsw_sp_fib_entry *fib_entry,
 6293				  enum mlxsw_reg_ralue_op op)
 6294{
 6295	enum mlxsw_reg_ralue_trap_action trap_action;
 6296	char ralue_pl[MLXSW_REG_RALUE_LEN];
 6297	u16 trap_id;
 6298
 6299	trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
 6300	trap_id = MLXSW_TRAP_ID_RTR_INGRESS1;
 6301
 6302	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
 6303	mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, trap_id, 0);
 6304	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
 6305}
 6306
 6307static int
 6308mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp,
 6309				 struct mlxsw_sp_fib_entry *fib_entry,
 6310				 enum mlxsw_reg_ralue_op op)
 6311{
 6312	struct mlxsw_sp_ipip_entry *ipip_entry = fib_entry->decap.ipip_entry;
 6313	const struct mlxsw_sp_ipip_ops *ipip_ops;
 6314	char ralue_pl[MLXSW_REG_RALUE_LEN];
 6315	int err;
 6316
 6317	if (WARN_ON(!ipip_entry))
 6318		return -EINVAL;
 6319
 6320	ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
 6321	err = ipip_ops->decap_config(mlxsw_sp, ipip_entry,
 6322				     fib_entry->decap.tunnel_index);
 6323	if (err)
 6324		return err;
 6325
 6326	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
 6327	mlxsw_reg_ralue_act_ip2me_tun_pack(ralue_pl,
 6328					   fib_entry->decap.tunnel_index);
 6329	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
 6330}
 6331
 6332static int mlxsw_sp_fib_entry_op_nve_decap(struct mlxsw_sp *mlxsw_sp,
 6333					   struct mlxsw_sp_fib_entry *fib_entry,
 6334					   enum mlxsw_reg_ralue_op op)
 6335{
 6336	char ralue_pl[MLXSW_REG_RALUE_LEN];
 6337
 6338	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
 6339	mlxsw_reg_ralue_act_ip2me_tun_pack(ralue_pl,
 6340					   fib_entry->decap.tunnel_index);
 6341	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
 6342}
 6343
 6344static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
 6345				   struct mlxsw_sp_fib_entry *fib_entry,
 6346				   enum mlxsw_reg_ralue_op op)
 6347{
 6348	switch (fib_entry->type) {
 6349	case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
 6350		return mlxsw_sp_fib_entry_op_remote(mlxsw_sp, fib_entry, op);
 6351	case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
 6352		return mlxsw_sp_fib_entry_op_local(mlxsw_sp, fib_entry, op);
 6353	case MLXSW_SP_FIB_ENTRY_TYPE_TRAP:
 6354		return mlxsw_sp_fib_entry_op_trap(mlxsw_sp, fib_entry, op);
 6355	case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE:
 6356		return mlxsw_sp_fib_entry_op_blackhole(mlxsw_sp, fib_entry, op);
 6357	case MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE:
 6358		return mlxsw_sp_fib_entry_op_unreachable(mlxsw_sp, fib_entry,
 6359							 op);
 6360	case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
 6361		return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp,
 6362							fib_entry, op);
 6363	case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP:
 6364		return mlxsw_sp_fib_entry_op_nve_decap(mlxsw_sp, fib_entry, op);
 6365	}
 6366	return -EINVAL;
 6367}
 6368
 6369static int mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
 6370				 struct mlxsw_sp_fib_entry *fib_entry,
 6371				 enum mlxsw_reg_ralue_op op)
 6372{
 6373	int err = __mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry, op);
 6374
 6375	if (err)
 6376		return err;
 6377
 6378	mlxsw_sp_fib_entry_hw_flags_refresh(mlxsw_sp, fib_entry, op);
 6379
 6380	return err;
 6381}
 6382
 6383static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp,
 6384				     struct mlxsw_sp_fib_entry *fib_entry)
 6385{
 6386	return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry,
 6387				     MLXSW_REG_RALUE_OP_WRITE_WRITE);
 6388}
 6389
 6390static int mlxsw_sp_fib_entry_del(struct mlxsw_sp *mlxsw_sp,
 6391				  struct mlxsw_sp_fib_entry *fib_entry)
 6392{
 6393	return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry,
 6394				     MLXSW_REG_RALUE_OP_WRITE_DELETE);
 6395}
 6396
 6397static int
 6398mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp,
 6399			     const struct fib_entry_notifier_info *fen_info,
 6400			     struct mlxsw_sp_fib_entry *fib_entry)
 6401{
 6402	struct mlxsw_sp_nexthop_group_info *nhgi = fib_entry->nh_group->nhgi;
 6403	union mlxsw_sp_l3addr dip = { .addr4 = htonl(fen_info->dst) };
 6404	struct mlxsw_sp_router *router = mlxsw_sp->router;
 6405	u32 tb_id = mlxsw_sp_fix_tb_id(fen_info->tb_id);
 6406	int ifindex = nhgi->nexthops[0].ifindex;
 6407	struct mlxsw_sp_ipip_entry *ipip_entry;
 6408
 6409	switch (fen_info->type) {
 6410	case RTN_LOCAL:
 6411		ipip_entry = mlxsw_sp_ipip_entry_find_by_decap(mlxsw_sp, ifindex,
 6412							       MLXSW_SP_L3_PROTO_IPV4, dip);
 6413		if (ipip_entry && ipip_entry->ol_dev->flags & IFF_UP) {
 6414			fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP;
 6415			return mlxsw_sp_fib_entry_decap_init(mlxsw_sp,
 6416							     fib_entry,
 6417							     ipip_entry);
 6418		}
 6419		if (mlxsw_sp_router_nve_is_decap(mlxsw_sp, tb_id,
 6420						 MLXSW_SP_L3_PROTO_IPV4,
 6421						 &dip)) {
 6422			u32 tunnel_index;
 6423
 6424			tunnel_index = router->nve_decap_config.tunnel_index;
 6425			fib_entry->decap.tunnel_index = tunnel_index;
 6426			fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP;
 6427			return 0;
 6428		}
 6429		fallthrough;
 6430	case RTN_BROADCAST:
 6431		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
 6432		return 0;
 6433	case RTN_BLACKHOLE:
 6434		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE;
 6435		return 0;
 6436	case RTN_UNREACHABLE:
 6437	case RTN_PROHIBIT:
 6438		/* Packets hitting these routes need to be trapped, but
 6439		 * can do so with a lower priority than packets directed
 6440		 * at the host, so use action type local instead of trap.
 6441		 */
 6442		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE;
 6443		return 0;
 6444	case RTN_UNICAST:
 6445		if (nhgi->gateway)
 6446			fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
 6447		else
 6448			fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
 6449		return 0;
 6450	default:
 6451		return -EINVAL;
 6452	}
 6453}
 6454
 6455static void
 6456mlxsw_sp_fib_entry_type_unset(struct mlxsw_sp *mlxsw_sp,
 6457			      struct mlxsw_sp_fib_entry *fib_entry)
 6458{
 6459	switch (fib_entry->type) {
 6460	case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
 6461		mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, fib_entry);
 6462		break;
 6463	default:
 6464		break;
 6465	}
 6466}
 6467
 6468static void
 6469mlxsw_sp_fib4_entry_type_unset(struct mlxsw_sp *mlxsw_sp,
 6470			       struct mlxsw_sp_fib4_entry *fib4_entry)
 6471{
 6472	mlxsw_sp_fib_entry_type_unset(mlxsw_sp, &fib4_entry->common);
 6473}
 6474
 6475static struct mlxsw_sp_fib4_entry *
 6476mlxsw_sp_fib4_entry_create(struct mlxsw_sp *mlxsw_sp,
 6477			   struct mlxsw_sp_fib_node *fib_node,
 6478			   const struct fib_entry_notifier_info *fen_info)
 6479{
 6480	struct mlxsw_sp_fib4_entry *fib4_entry;
 6481	struct mlxsw_sp_fib_entry *fib_entry;
 6482	int err;
 6483
 6484	fib4_entry = kzalloc(sizeof(*fib4_entry), GFP_KERNEL);
 6485	if (!fib4_entry)
 6486		return ERR_PTR(-ENOMEM);
 6487	fib_entry = &fib4_entry->common;
 6488
 6489	err = mlxsw_sp_nexthop4_group_get(mlxsw_sp, fib_entry, fen_info->fi);
 6490	if (err)
 6491		goto err_nexthop4_group_get;
 6492
 6493	err = mlxsw_sp_nexthop_group_vr_link(fib_entry->nh_group,
 6494					     fib_node->fib);
 6495	if (err)
 6496		goto err_nexthop_group_vr_link;
 6497
 6498	err = mlxsw_sp_fib4_entry_type_set(mlxsw_sp, fen_info, fib_entry);
 6499	if (err)
 6500		goto err_fib4_entry_type_set;
 6501
 6502	fib4_entry->fi = fen_info->fi;
 6503	fib_info_hold(fib4_entry->fi);
 6504	fib4_entry->tb_id = fen_info->tb_id;
 6505	fib4_entry->type = fen_info->type;
 6506	fib4_entry->dscp = fen_info->dscp;
 6507
 6508	fib_entry->fib_node = fib_node;
 6509
 6510	return fib4_entry;
 6511
 6512err_fib4_entry_type_set:
 6513	mlxsw_sp_nexthop_group_vr_unlink(fib_entry->nh_group, fib_node->fib);
 6514err_nexthop_group_vr_link:
 6515	mlxsw_sp_nexthop4_group_put(mlxsw_sp, &fib4_entry->common);
 6516err_nexthop4_group_get:
 6517	kfree(fib4_entry);
 6518	return ERR_PTR(err);
 6519}
 6520
 6521static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp *mlxsw_sp,
 6522					struct mlxsw_sp_fib4_entry *fib4_entry)
 6523{
 6524	struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node;
 6525
 6526	fib_info_put(fib4_entry->fi);
 6527	mlxsw_sp_fib4_entry_type_unset(mlxsw_sp, fib4_entry);
 6528	mlxsw_sp_nexthop_group_vr_unlink(fib4_entry->common.nh_group,
 6529					 fib_node->fib);
 6530	mlxsw_sp_nexthop4_group_put(mlxsw_sp, &fib4_entry->common);
 6531	kfree(fib4_entry);
 6532}
 6533
 6534static struct mlxsw_sp_fib4_entry *
 6535mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp *mlxsw_sp,
 6536			   const struct fib_entry_notifier_info *fen_info)
 6537{
 6538	struct mlxsw_sp_fib4_entry *fib4_entry;
 6539	struct mlxsw_sp_fib_node *fib_node;
 6540	struct mlxsw_sp_fib *fib;
 6541	struct mlxsw_sp_vr *vr;
 6542
 6543	vr = mlxsw_sp_vr_find(mlxsw_sp, fen_info->tb_id);
 6544	if (!vr)
 6545		return NULL;
 6546	fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV4);
 6547
 6548	fib_node = mlxsw_sp_fib_node_lookup(fib, &fen_info->dst,
 6549					    sizeof(fen_info->dst),
 6550					    fen_info->dst_len);
 6551	if (!fib_node)
 6552		return NULL;
 6553
 6554	fib4_entry = container_of(fib_node->fib_entry,
 6555				  struct mlxsw_sp_fib4_entry, common);
 6556	if (fib4_entry->tb_id == fen_info->tb_id &&
 6557	    fib4_entry->dscp == fen_info->dscp &&
 6558	    fib4_entry->type == fen_info->type &&
 6559	    fib4_entry->fi == fen_info->fi)
 6560		return fib4_entry;
 6561
 6562	return NULL;
 6563}
 6564
 6565static const struct rhashtable_params mlxsw_sp_fib_ht_params = {
 6566	.key_offset = offsetof(struct mlxsw_sp_fib_node, key),
 6567	.head_offset = offsetof(struct mlxsw_sp_fib_node, ht_node),
 6568	.key_len = sizeof(struct mlxsw_sp_fib_key),
 6569	.automatic_shrinking = true,
 6570};
 6571
 6572static int mlxsw_sp_fib_node_insert(struct mlxsw_sp_fib *fib,
 6573				    struct mlxsw_sp_fib_node *fib_node)
 6574{
 6575	return rhashtable_insert_fast(&fib->ht, &fib_node->ht_node,
 6576				      mlxsw_sp_fib_ht_params);
 6577}
 6578
 6579static void mlxsw_sp_fib_node_remove(struct mlxsw_sp_fib *fib,
 6580				     struct mlxsw_sp_fib_node *fib_node)
 6581{
 6582	rhashtable_remove_fast(&fib->ht, &fib_node->ht_node,
 6583			       mlxsw_sp_fib_ht_params);
 6584}
 6585
 6586static struct mlxsw_sp_fib_node *
 6587mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr,
 6588			 size_t addr_len, unsigned char prefix_len)
 6589{
 6590	struct mlxsw_sp_fib_key key;
 6591
 6592	memset(&key, 0, sizeof(key));
 6593	memcpy(key.addr, addr, addr_len);
 6594	key.prefix_len = prefix_len;
 6595	return rhashtable_lookup_fast(&fib->ht, &key, mlxsw_sp_fib_ht_params);
 6596}
 6597
 6598static struct mlxsw_sp_fib_node *
 6599mlxsw_sp_fib_node_create(struct mlxsw_sp_fib *fib, const void *addr,
 6600			 size_t addr_len, unsigned char prefix_len)
 6601{
 6602	struct mlxsw_sp_fib_node *fib_node;
 6603
 6604	fib_node = kzalloc(sizeof(*fib_node), GFP_KERNEL);
 6605	if (!fib_node)
 6606		return NULL;
 6607
 6608	list_add(&fib_node->list, &fib->node_list);
 6609	memcpy(fib_node->key.addr, addr, addr_len);
 6610	fib_node->key.prefix_len = prefix_len;
 6611
 6612	return fib_node;
 6613}
 6614
 6615static void mlxsw_sp_fib_node_destroy(struct mlxsw_sp_fib_node *fib_node)
 6616{
 6617	list_del(&fib_node->list);
 6618	kfree(fib_node);
 6619}
 6620
 6621static int mlxsw_sp_fib_lpm_tree_link(struct mlxsw_sp *mlxsw_sp,
 6622				      struct mlxsw_sp_fib_node *fib_node)
 6623{
 6624	struct mlxsw_sp_prefix_usage req_prefix_usage;
 6625	struct mlxsw_sp_fib *fib = fib_node->fib;
 6626	struct mlxsw_sp_lpm_tree *lpm_tree;
 6627	int err;
 6628
 6629	lpm_tree = mlxsw_sp->router->lpm.proto_trees[fib->proto];
 6630	if (lpm_tree->prefix_ref_count[fib_node->key.prefix_len] != 0)
 6631		goto out;
 6632
 6633	mlxsw_sp_prefix_usage_cpy(&req_prefix_usage, &lpm_tree->prefix_usage);
 6634	mlxsw_sp_prefix_usage_set(&req_prefix_usage, fib_node->key.prefix_len);
 6635	lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
 6636					 fib->proto);
 6637	if (IS_ERR(lpm_tree))
 6638		return PTR_ERR(lpm_tree);
 6639
 6640	err = mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp, fib, lpm_tree);
 6641	if (err)
 6642		goto err_lpm_tree_replace;
 6643
 6644out:
 6645	lpm_tree->prefix_ref_count[fib_node->key.prefix_len]++;
 6646	return 0;
 6647
 6648err_lpm_tree_replace:
 6649	mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
 6650	return err;
 6651}
 6652
 6653static void mlxsw_sp_fib_lpm_tree_unlink(struct mlxsw_sp *mlxsw_sp,
 6654					 struct mlxsw_sp_fib_node *fib_node)
 6655{
 6656	struct mlxsw_sp_lpm_tree *lpm_tree = fib_node->fib->lpm_tree;
 6657	struct mlxsw_sp_prefix_usage req_prefix_usage;
 6658	struct mlxsw_sp_fib *fib = fib_node->fib;
 6659	int err;
 6660
 6661	if (--lpm_tree->prefix_ref_count[fib_node->key.prefix_len] != 0)
 6662		return;
 6663	/* Try to construct a new LPM tree from the current prefix usage
 6664	 * minus the unused one. If we fail, continue using the old one.
 6665	 */
 6666	mlxsw_sp_prefix_usage_cpy(&req_prefix_usage, &lpm_tree->prefix_usage);
 6667	mlxsw_sp_prefix_usage_clear(&req_prefix_usage,
 6668				    fib_node->key.prefix_len);
 6669	lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
 6670					 fib->proto);
 6671	if (IS_ERR(lpm_tree))
 6672		return;
 6673
 6674	err = mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp, fib, lpm_tree);
 6675	if (err)
 6676		goto err_lpm_tree_replace;
 6677
 6678	return;
 6679
 6680err_lpm_tree_replace:
 6681	mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
 6682}
 6683
 6684static int mlxsw_sp_fib_node_init(struct mlxsw_sp *mlxsw_sp,
 6685				  struct mlxsw_sp_fib_node *fib_node,
 6686				  struct mlxsw_sp_fib *fib)
 6687{
 6688	int err;
 6689
 6690	err = mlxsw_sp_fib_node_insert(fib, fib_node);
 6691	if (err)
 6692		return err;
 6693	fib_node->fib = fib;
 6694
 6695	err = mlxsw_sp_fib_lpm_tree_link(mlxsw_sp, fib_node);
 6696	if (err)
 6697		goto err_fib_lpm_tree_link;
 6698
 6699	return 0;
 6700
 6701err_fib_lpm_tree_link:
 6702	fib_node->fib = NULL;
 6703	mlxsw_sp_fib_node_remove(fib, fib_node);
 6704	return err;
 6705}
 6706
 6707static void mlxsw_sp_fib_node_fini(struct mlxsw_sp *mlxsw_sp,
 6708				   struct mlxsw_sp_fib_node *fib_node)
 6709{
 6710	struct mlxsw_sp_fib *fib = fib_node->fib;
 6711
 6712	mlxsw_sp_fib_lpm_tree_unlink(mlxsw_sp, fib_node);
 6713	fib_node->fib = NULL;
 6714	mlxsw_sp_fib_node_remove(fib, fib_node);
 6715}
 6716
 6717static struct mlxsw_sp_fib_node *
 6718mlxsw_sp_fib_node_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, const void *addr,
 6719		      size_t addr_len, unsigned char prefix_len,
 6720		      enum mlxsw_sp_l3proto proto)
 6721{
 6722	struct mlxsw_sp_fib_node *fib_node;
 6723	struct mlxsw_sp_fib *fib;
 6724	struct mlxsw_sp_vr *vr;
 6725	int err;
 6726
 6727	vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id, NULL);
 6728	if (IS_ERR(vr))
 6729		return ERR_CAST(vr);
 6730	fib = mlxsw_sp_vr_fib(vr, proto);
 6731
 6732	fib_node = mlxsw_sp_fib_node_lookup(fib, addr, addr_len, prefix_len);
 6733	if (fib_node)
 6734		return fib_node;
 6735
 6736	fib_node = mlxsw_sp_fib_node_create(fib, addr, addr_len, prefix_len);
 6737	if (!fib_node) {
 6738		err = -ENOMEM;
 6739		goto err_fib_node_create;
 6740	}
 6741
 6742	err = mlxsw_sp_fib_node_init(mlxsw_sp, fib_node, fib);
 6743	if (err)
 6744		goto err_fib_node_init;
 6745
 6746	return fib_node;
 6747
 6748err_fib_node_init:
 6749	mlxsw_sp_fib_node_destroy(fib_node);
 6750err_fib_node_create:
 6751	mlxsw_sp_vr_put(mlxsw_sp, vr);
 6752	return ERR_PTR(err);
 6753}
 6754
 6755static void mlxsw_sp_fib_node_put(struct mlxsw_sp *mlxsw_sp,
 6756				  struct mlxsw_sp_fib_node *fib_node)
 6757{
 6758	struct mlxsw_sp_vr *vr = fib_node->fib->vr;
 6759
 6760	if (fib_node->fib_entry)
 6761		return;
 6762	mlxsw_sp_fib_node_fini(mlxsw_sp, fib_node);
 6763	mlxsw_sp_fib_node_destroy(fib_node);
 6764	mlxsw_sp_vr_put(mlxsw_sp, vr);
 6765}
 6766
 6767static int mlxsw_sp_fib_node_entry_link(struct mlxsw_sp *mlxsw_sp,
 6768					struct mlxsw_sp_fib_entry *fib_entry)
 6769{
 6770	struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
 6771	int err;
 6772
 6773	fib_node->fib_entry = fib_entry;
 6774
 6775	err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
 6776	if (err)
 6777		goto err_fib_entry_update;
 6778
 6779	return 0;
 6780
 6781err_fib_entry_update:
 6782	fib_node->fib_entry = NULL;
 6783	return err;
 6784}
 6785
 6786static void
 6787mlxsw_sp_fib_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
 6788			       struct mlxsw_sp_fib_entry *fib_entry)
 6789{
 6790	struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
 6791
 6792	mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry);
 6793	fib_node->fib_entry = NULL;
 6794}
 6795
 6796static bool mlxsw_sp_fib4_allow_replace(struct mlxsw_sp_fib4_entry *fib4_entry)
 6797{
 6798	struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node;
 6799	struct mlxsw_sp_fib4_entry *fib4_replaced;
 6800
 6801	if (!fib_node->fib_entry)
 6802		return true;
 6803
 6804	fib4_replaced = container_of(fib_node->fib_entry,
 6805				     struct mlxsw_sp_fib4_entry, common);
 6806	if (fib4_entry->tb_id == RT_TABLE_MAIN &&
 6807	    fib4_replaced->tb_id == RT_TABLE_LOCAL)
 6808		return false;
 6809
 6810	return true;
 6811}
 6812
 6813static int
 6814mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
 6815			     const struct fib_entry_notifier_info *fen_info)
 6816{
 6817	struct mlxsw_sp_fib4_entry *fib4_entry, *fib4_replaced;
 6818	struct mlxsw_sp_fib_entry *replaced;
 6819	struct mlxsw_sp_fib_node *fib_node;
 6820	int err;
 6821
 6822	if (fen_info->fi->nh &&
 6823	    !mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, fen_info->fi->nh->id))
 6824		return 0;
 6825
 6826	fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, fen_info->tb_id,
 6827					 &fen_info->dst, sizeof(fen_info->dst),
 6828					 fen_info->dst_len,
 6829					 MLXSW_SP_L3_PROTO_IPV4);
 6830	if (IS_ERR(fib_node)) {
 6831		dev_warn(mlxsw_sp->bus_info->dev, "Failed to get FIB node\n");
 6832		return PTR_ERR(fib_node);
 6833	}
 6834
 6835	fib4_entry = mlxsw_sp_fib4_entry_create(mlxsw_sp, fib_node, fen_info);
 6836	if (IS_ERR(fib4_entry)) {
 6837		dev_warn(mlxsw_sp->bus_info->dev, "Failed to create FIB entry\n");
 6838		err = PTR_ERR(fib4_entry);
 6839		goto err_fib4_entry_create;
 6840	}
 6841
 6842	if (!mlxsw_sp_fib4_allow_replace(fib4_entry)) {
 6843		mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
 6844		mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
 6845		return 0;
 6846	}
 6847
 6848	replaced = fib_node->fib_entry;
 6849	err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib4_entry->common);
 6850	if (err) {
 6851		dev_warn(mlxsw_sp->bus_info->dev, "Failed to link FIB entry to node\n");
 6852		goto err_fib_node_entry_link;
 6853	}
 6854
 6855	/* Nothing to replace */
 6856	if (!replaced)
 6857		return 0;
 6858
 6859	mlxsw_sp_fib_entry_hw_flags_clear(mlxsw_sp, replaced);
 6860	fib4_replaced = container_of(replaced, struct mlxsw_sp_fib4_entry,
 6861				     common);
 6862	mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_replaced);
 6863
 6864	return 0;
 6865
 6866err_fib_node_entry_link:
 6867	fib_node->fib_entry = replaced;
 6868	mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
 6869err_fib4_entry_create:
 6870	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
 6871	return err;
 6872}
 6873
 6874static void mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp,
 6875				     struct fib_entry_notifier_info *fen_info)
 6876{
 6877	struct mlxsw_sp_fib4_entry *fib4_entry;
 6878	struct mlxsw_sp_fib_node *fib_node;
 6879
 6880	fib4_entry = mlxsw_sp_fib4_entry_lookup(mlxsw_sp, fen_info);
 6881	if (!fib4_entry)
 6882		return;
 6883	fib_node = fib4_entry->common.fib_node;
 6884
 6885	mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &fib4_entry->common);
 6886	mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
 6887	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
 6888}
 6889
 6890static bool mlxsw_sp_fib6_rt_should_ignore(const struct fib6_info *rt)
 6891{
 6892	/* Multicast routes aren't supported, so ignore them. Neighbour
 6893	 * Discovery packets are specifically trapped.
 6894	 */
 6895	if (ipv6_addr_type(&rt->fib6_dst.addr) & IPV6_ADDR_MULTICAST)
 6896		return true;
 6897
 6898	/* Cloned routes are irrelevant in the forwarding path. */
 6899	if (rt->fib6_flags & RTF_CACHE)
 6900		return true;
 6901
 6902	return false;
 6903}
 6904
 6905static struct mlxsw_sp_rt6 *mlxsw_sp_rt6_create(struct fib6_info *rt)
 6906{
 6907	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
 6908
 6909	mlxsw_sp_rt6 = kzalloc(sizeof(*mlxsw_sp_rt6), GFP_KERNEL);
 6910	if (!mlxsw_sp_rt6)
 6911		return ERR_PTR(-ENOMEM);
 6912
 6913	/* In case of route replace, replaced route is deleted with
 6914	 * no notification. Take reference to prevent accessing freed
 6915	 * memory.
 6916	 */
 6917	mlxsw_sp_rt6->rt = rt;
 6918	fib6_info_hold(rt);
 6919
 6920	return mlxsw_sp_rt6;
 6921}
 6922
 6923#if IS_ENABLED(CONFIG_IPV6)
 6924static void mlxsw_sp_rt6_release(struct fib6_info *rt)
 6925{
 6926	fib6_info_release(rt);
 6927}
 6928#else
 6929static void mlxsw_sp_rt6_release(struct fib6_info *rt)
 6930{
 6931}
 6932#endif
 6933
 6934static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
 6935{
 6936	struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
 6937
 6938	if (!mlxsw_sp_rt6->rt->nh)
 6939		fib6_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
 6940	mlxsw_sp_rt6_release(mlxsw_sp_rt6->rt);
 6941	kfree(mlxsw_sp_rt6);
 6942}
 6943
 6944static struct fib6_info *
 6945mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry)
 6946{
 6947	return list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
 6948				list)->rt;
 6949}
 6950
 6951static struct mlxsw_sp_rt6 *
 6952mlxsw_sp_fib6_entry_rt_find(const struct mlxsw_sp_fib6_entry *fib6_entry,
 6953			    const struct fib6_info *rt)
 6954{
 6955	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
 6956
 6957	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
 6958		if (mlxsw_sp_rt6->rt == rt)
 6959			return mlxsw_sp_rt6;
 6960	}
 6961
 6962	return NULL;
 6963}
 6964
 6965static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp *mlxsw_sp,
 6966					const struct fib6_info *rt,
 6967					enum mlxsw_sp_ipip_type *ret)
 6968{
 6969	return rt->fib6_nh->fib_nh_dev &&
 6970	       mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->fib6_nh->fib_nh_dev, ret);
 6971}
 6972
 6973static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
 6974				  struct mlxsw_sp_nexthop_group *nh_grp,
 6975				  struct mlxsw_sp_nexthop *nh,
 6976				  const struct fib6_info *rt)
 6977{
 6978	struct net_device *dev = rt->fib6_nh->fib_nh_dev;
 6979	int err;
 6980
 6981	nh->nhgi = nh_grp->nhgi;
 6982	nh->nh_weight = rt->fib6_nh->fib_nh_weight;
 6983	memcpy(&nh->gw_addr, &rt->fib6_nh->fib_nh_gw6, sizeof(nh->gw_addr));
 6984#if IS_ENABLED(CONFIG_IPV6)
 6985	nh->neigh_tbl = &nd_tbl;
 6986#endif
 6987
 6988	err = mlxsw_sp_nexthop_counter_enable(mlxsw_sp, nh);
 6989	if (err)
 6990		return err;
 6991
 6992	list_add_tail(&nh->router_list_node, &mlxsw_sp->router->nexthop_list);
 6993
 6994	if (!dev)
 6995		return 0;
 6996	nh->ifindex = dev->ifindex;
 6997
 6998	err = mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
 6999	if (err)
 7000		goto err_nexthop_type_init;
 7001
 7002	return 0;
 7003
 7004err_nexthop_type_init:
 7005	list_del(&nh->router_list_node);
 7006	mlxsw_sp_nexthop_counter_disable(mlxsw_sp, nh);
 7007	return err;
 7008}
 7009
 7010static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp,
 7011				   struct mlxsw_sp_nexthop *nh)
 7012{
 7013	mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
 7014	list_del(&nh->router_list_node);
 7015	mlxsw_sp_nexthop_counter_disable(mlxsw_sp, nh);
 7016}
 7017
 7018static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp *mlxsw_sp,
 7019				    const struct fib6_info *rt)
 7020{
 7021	return rt->fib6_nh->fib_nh_gw_family ||
 7022	       mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL);
 7023}
 7024
 7025static int
 7026mlxsw_sp_nexthop6_group_info_init(struct mlxsw_sp *mlxsw_sp,
 7027				  struct mlxsw_sp_nexthop_group *nh_grp,
 7028				  struct mlxsw_sp_fib6_entry *fib6_entry)
 7029{
 7030	struct mlxsw_sp_nexthop_group_info *nhgi;
 7031	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
 7032	struct mlxsw_sp_nexthop *nh;
 7033	int err, i;
 7034
 7035	nhgi = kzalloc(struct_size(nhgi, nexthops, fib6_entry->nrt6),
 7036		       GFP_KERNEL);
 7037	if (!nhgi)
 7038		return -ENOMEM;
 7039	nh_grp->nhgi = nhgi;
 7040	nhgi->nh_grp = nh_grp;
 7041	mlxsw_sp_rt6 = list_first_entry(&fib6_entry->rt6_list,
 7042					struct mlxsw_sp_rt6, list);
 7043	nhgi->gateway = mlxsw_sp_rt6_is_gateway(mlxsw_sp, mlxsw_sp_rt6->rt);
 7044	nhgi->count = fib6_entry->nrt6;
 7045	for (i = 0; i < nhgi->count; i++) {
 7046		struct fib6_info *rt = mlxsw_sp_rt6->rt;
 7047
 7048		nh = &nhgi->nexthops[i];
 7049		err = mlxsw_sp_nexthop6_init(mlxsw_sp, nh_grp, nh, rt);
 7050		if (err)
 7051			goto err_nexthop6_init;
 7052		mlxsw_sp_rt6 = list_next_entry(mlxsw_sp_rt6, list);
 7053	}
 7054	nh_grp->nhgi = nhgi;
 7055	err = mlxsw_sp_nexthop_group_inc(mlxsw_sp);
 7056	if (err)
 7057		goto err_group_inc;
 7058	err = mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
 7059	if (err)
 7060		goto err_group_refresh;
 7061
 7062	return 0;
 7063
 7064err_group_refresh:
 7065	mlxsw_sp_nexthop_group_dec(mlxsw_sp);
 7066err_group_inc:
 7067	i = nhgi->count;
 7068err_nexthop6_init:
 7069	for (i--; i >= 0; i--) {
 7070		nh = &nhgi->nexthops[i];
 7071		mlxsw_sp_nexthop6_fini(mlxsw_sp, nh);
 7072	}
 7073	kfree(nhgi);
 7074	return err;
 7075}
 7076
 7077static void
 7078mlxsw_sp_nexthop6_group_info_fini(struct mlxsw_sp *mlxsw_sp,
 7079				  struct mlxsw_sp_nexthop_group *nh_grp)
 7080{
 7081	struct mlxsw_sp_nexthop_group_info *nhgi = nh_grp->nhgi;
 7082	int i;
 7083
 7084	mlxsw_sp_nexthop_group_dec(mlxsw_sp);
 7085	for (i = nhgi->count - 1; i >= 0; i--) {
 7086		struct mlxsw_sp_nexthop *nh = &nhgi->nexthops[i];
 7087
 7088		mlxsw_sp_nexthop6_fini(mlxsw_sp, nh);
 7089	}
 7090	mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
 7091	WARN_ON_ONCE(nhgi->adj_index_valid);
 7092	kfree(nhgi);
 7093}
 7094
 7095static struct mlxsw_sp_nexthop_group *
 7096mlxsw_sp_nexthop6_group_create(struct mlxsw_sp *mlxsw_sp,
 7097			       struct mlxsw_sp_fib6_entry *fib6_entry)
 7098{
 7099	struct mlxsw_sp_nexthop_group *nh_grp;
 7100	int err;
 7101
 7102	nh_grp = kzalloc(sizeof(*nh_grp), GFP_KERNEL);
 7103	if (!nh_grp)
 7104		return ERR_PTR(-ENOMEM);
 7105	INIT_LIST_HEAD(&nh_grp->vr_list);
 7106	err = rhashtable_init(&nh_grp->vr_ht,
 7107			      &mlxsw_sp_nexthop_group_vr_ht_params);
 7108	if (err)
 7109		goto err_nexthop_group_vr_ht_init;
 7110	INIT_LIST_HEAD(&nh_grp->fib_list);
 7111	nh_grp->type = MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6;
 7112
 7113	err = mlxsw_sp_nexthop6_group_info_init(mlxsw_sp, nh_grp, fib6_entry);
 7114	if (err)
 7115		goto err_nexthop_group_info_init;
 7116
 7117	err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
 7118	if (err)
 7119		goto err_nexthop_group_insert;
 7120
 7121	nh_grp->can_destroy = true;
 7122
 7123	return nh_grp;
 7124
 7125err_nexthop_group_insert:
 7126	mlxsw_sp_nexthop6_group_info_fini(mlxsw_sp, nh_grp);
 7127err_nexthop_group_info_init:
 7128	rhashtable_destroy(&nh_grp->vr_ht);
 7129err_nexthop_group_vr_ht_init:
 7130	kfree(nh_grp);
 7131	return ERR_PTR(err);
 7132}
 7133
 7134static void
 7135mlxsw_sp_nexthop6_group_destroy(struct mlxsw_sp *mlxsw_sp,
 7136				struct mlxsw_sp_nexthop_group *nh_grp)
 7137{
 7138	if (!nh_grp->can_destroy)
 7139		return;
 7140	mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
 7141	mlxsw_sp_nexthop6_group_info_fini(mlxsw_sp, nh_grp);
 7142	WARN_ON_ONCE(!list_empty(&nh_grp->vr_list));
 7143	rhashtable_destroy(&nh_grp->vr_ht);
 7144	kfree(nh_grp);
 7145}
 7146
 7147static int mlxsw_sp_nexthop6_group_get(struct mlxsw_sp *mlxsw_sp,
 7148				       struct mlxsw_sp_fib6_entry *fib6_entry)
 7149{
 7150	struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
 7151	struct mlxsw_sp_nexthop_group *nh_grp;
 7152
 7153	if (rt->nh) {
 7154		nh_grp = mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp,
 7155							   rt->nh->id);
 7156		if (WARN_ON_ONCE(!nh_grp))
 7157			return -EINVAL;
 7158		goto out;
 7159	}
 7160
 7161	nh_grp = mlxsw_sp_nexthop6_group_lookup(mlxsw_sp, fib6_entry);
 7162	if (!nh_grp) {
 7163		nh_grp = mlxsw_sp_nexthop6_group_create(mlxsw_sp, fib6_entry);
 7164		if (IS_ERR(nh_grp))
 7165			return PTR_ERR(nh_grp);
 7166	}
 7167
 7168	/* The route and the nexthop are described by the same struct, so we
 7169	 * need to the update the nexthop offload indication for the new route.
 7170	 */
 7171	__mlxsw_sp_nexthop6_group_offload_refresh(nh_grp, fib6_entry);
 7172
 7173out:
 7174	list_add_tail(&fib6_entry->common.nexthop_group_node,
 7175		      &nh_grp->fib_list);
 7176	fib6_entry->common.nh_group = nh_grp;
 7177
 7178	return 0;
 7179}
 7180
 7181static void mlxsw_sp_nexthop6_group_put(struct mlxsw_sp *mlxsw_sp,
 7182					struct mlxsw_sp_fib_entry *fib_entry)
 7183{
 7184	struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
 7185
 7186	list_del(&fib_entry->nexthop_group_node);
 7187	if (!list_empty(&nh_grp->fib_list))
 7188		return;
 7189
 7190	if (nh_grp->type == MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ) {
 7191		mlxsw_sp_nexthop_obj_group_destroy(mlxsw_sp, nh_grp);
 7192		return;
 7193	}
 7194
 7195	mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, nh_grp);
 7196}
 7197
 7198static int
 7199mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp,
 7200			       struct mlxsw_sp_fib6_entry *fib6_entry)
 7201{
 7202	struct mlxsw_sp_nexthop_group *old_nh_grp = fib6_entry->common.nh_group;
 7203	struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
 7204	int err;
 7205
 7206	mlxsw_sp_nexthop_group_vr_unlink(old_nh_grp, fib_node->fib);
 7207	fib6_entry->common.nh_group = NULL;
 7208	list_del(&fib6_entry->common.nexthop_group_node);
 7209
 7210	err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
 7211	if (err)
 7212		goto err_nexthop6_group_get;
 7213
 7214	err = mlxsw_sp_nexthop_group_vr_link(fib6_entry->common.nh_group,
 7215					     fib_node->fib);
 7216	if (err)
 7217		goto err_nexthop_group_vr_link;
 7218
 7219	/* In case this entry is offloaded, then the adjacency index
 7220	 * currently associated with it in the device's table is that
 7221	 * of the old group. Start using the new one instead.
 7222	 */
 7223	err = mlxsw_sp_fib_entry_update(mlxsw_sp, &fib6_entry->common);
 7224	if (err)
 7225		goto err_fib_entry_update;
 7226
 7227	if (list_empty(&old_nh_grp->fib_list))
 7228		mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, old_nh_grp);
 7229
 7230	return 0;
 7231
 7232err_fib_entry_update:
 7233	mlxsw_sp_nexthop_group_vr_unlink(fib6_entry->common.nh_group,
 7234					 fib_node->fib);
 7235err_nexthop_group_vr_link:
 7236	mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
 7237err_nexthop6_group_get:
 7238	list_add_tail(&fib6_entry->common.nexthop_group_node,
 7239		      &old_nh_grp->fib_list);
 7240	fib6_entry->common.nh_group = old_nh_grp;
 7241	mlxsw_sp_nexthop_group_vr_link(old_nh_grp, fib_node->fib);
 7242	return err;
 7243}
 7244
 7245static int
 7246mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp *mlxsw_sp,
 7247				struct mlxsw_sp_fib6_entry *fib6_entry,
 7248				struct fib6_info **rt_arr, unsigned int nrt6)
 7249{
 7250	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
 7251	int err, i;
 7252
 7253	for (i = 0; i < nrt6; i++) {
 7254		mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt_arr[i]);
 7255		if (IS_ERR(mlxsw_sp_rt6)) {
 7256			err = PTR_ERR(mlxsw_sp_rt6);
 7257			goto err_rt6_unwind;
 7258		}
 7259
 7260		list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
 7261		fib6_entry->nrt6++;
 7262	}
 7263
 7264	err = mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
 7265	if (err)
 7266		goto err_rt6_unwind;
 7267
 7268	return 0;
 7269
 7270err_rt6_unwind:
 7271	for (; i > 0; i--) {
 7272		fib6_entry->nrt6--;
 7273		mlxsw_sp_rt6 = list_last_entry(&fib6_entry->rt6_list,
 7274					       struct mlxsw_sp_rt6, list);
 7275		list_del(&mlxsw_sp_rt6->list);
 7276		mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
 7277	}
 7278	return err;
 7279}
 7280
 7281static void
 7282mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp *mlxsw_sp,
 7283				struct mlxsw_sp_fib6_entry *fib6_entry,
 7284				struct fib6_info **rt_arr, unsigned int nrt6)
 7285{
 7286	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
 7287	int i;
 7288
 7289	for (i = 0; i < nrt6; i++) {
 7290		mlxsw_sp_rt6 = mlxsw_sp_fib6_entry_rt_find(fib6_entry,
 7291							   rt_arr[i]);
 7292		if (WARN_ON_ONCE(!mlxsw_sp_rt6))
 7293			continue;
 7294
 7295		fib6_entry->nrt6--;
 7296		list_del(&mlxsw_sp_rt6->list);
 7297		mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
 7298	}
 7299
 7300	mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
 7301}
 7302
 7303static int
 7304mlxsw_sp_fib6_entry_type_set_local(struct mlxsw_sp *mlxsw_sp,
 7305				   struct mlxsw_sp_fib_entry *fib_entry,
 7306				   const struct fib6_info *rt)
 7307{
 7308	struct mlxsw_sp_nexthop_group_info *nhgi = fib_entry->nh_group->nhgi;
 7309	union mlxsw_sp_l3addr dip = { .addr6 = rt->fib6_dst.addr };
 7310	u32 tb_id = mlxsw_sp_fix_tb_id(rt->fib6_table->tb6_id);
 7311	struct mlxsw_sp_router *router = mlxsw_sp->router;
 7312	int ifindex = nhgi->nexthops[0].ifindex;
 7313	struct mlxsw_sp_ipip_entry *ipip_entry;
 7314
 7315	fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
 7316	ipip_entry = mlxsw_sp_ipip_entry_find_by_decap(mlxsw_sp, ifindex,
 7317						       MLXSW_SP_L3_PROTO_IPV6,
 7318						       dip);
 7319
 7320	if (ipip_entry && ipip_entry->ol_dev->flags & IFF_UP) {
 7321		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP;
 7322		return mlxsw_sp_fib_entry_decap_init(mlxsw_sp, fib_entry,
 7323						     ipip_entry);
 7324	}
 7325	if (mlxsw_sp_router_nve_is_decap(mlxsw_sp, tb_id,
 7326					 MLXSW_SP_L3_PROTO_IPV6, &dip)) {
 7327		u32 tunnel_index;
 7328
 7329		tunnel_index = router->nve_decap_config.tunnel_index;
 7330		fib_entry->decap.tunnel_index = tunnel_index;
 7331		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP;
 7332	}
 7333
 7334	return 0;
 7335}
 7336
 7337static int mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp,
 7338					struct mlxsw_sp_fib_entry *fib_entry,
 7339					const struct fib6_info *rt)
 7340{
 7341	if (rt->fib6_flags & RTF_LOCAL)
 7342		return mlxsw_sp_fib6_entry_type_set_local(mlxsw_sp, fib_entry,
 7343							  rt);
 7344	if (rt->fib6_flags & RTF_ANYCAST)
 7345		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
 7346	else if (rt->fib6_type == RTN_BLACKHOLE)
 7347		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE;
 7348	else if (rt->fib6_flags & RTF_REJECT)
 7349		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE;
 7350	else if (fib_entry->nh_group->nhgi->gateway)
 7351		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
 7352	else
 7353		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
 7354
 7355	return 0;
 7356}
 7357
 7358static void
 7359mlxsw_sp_fib6_entry_rt_destroy_all(struct mlxsw_sp_fib6_entry *fib6_entry)
 7360{
 7361	struct mlxsw_sp_rt6 *mlxsw_sp_rt6, *tmp;
 7362
 7363	list_for_each_entry_safe(mlxsw_sp_rt6, tmp, &fib6_entry->rt6_list,
 7364				 list) {
 7365		fib6_entry->nrt6--;
 7366		list_del(&mlxsw_sp_rt6->list);
 7367		mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
 7368	}
 7369}
 7370
 7371static struct mlxsw_sp_fib6_entry *
 7372mlxsw_sp_fib6_entry_create(struct mlxsw_sp *mlxsw_sp,
 7373			   struct mlxsw_sp_fib_node *fib_node,
 7374			   struct fib6_info **rt_arr, unsigned int nrt6)
 7375{
 7376	struct mlxsw_sp_fib6_entry *fib6_entry;
 7377	struct mlxsw_sp_fib_entry *fib_entry;
 7378	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
 7379	int err, i;
 7380
 7381	fib6_entry = kzalloc(sizeof(*fib6_entry), GFP_KERNEL);
 7382	if (!fib6_entry)
 7383		return ERR_PTR(-ENOMEM);
 7384	fib_entry = &fib6_entry->common;
 7385
 7386	INIT_LIST_HEAD(&fib6_entry->rt6_list);
 7387
 7388	for (i = 0; i < nrt6; i++) {
 7389		mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt_arr[i]);
 7390		if (IS_ERR(mlxsw_sp_rt6)) {
 7391			err = PTR_ERR(mlxsw_sp_rt6);
 7392			goto err_rt6_unwind;
 7393		}
 7394		list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
 7395		fib6_entry->nrt6++;
 7396	}
 7397
 7398	err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
 7399	if (err)
 7400		goto err_rt6_unwind;
 7401
 7402	err = mlxsw_sp_nexthop_group_vr_link(fib_entry->nh_group,
 7403					     fib_node->fib);
 7404	if (err)
 7405		goto err_nexthop_group_vr_link;
 7406
 7407	err = mlxsw_sp_fib6_entry_type_set(mlxsw_sp, fib_entry, rt_arr[0]);
 7408	if (err)
 7409		goto err_fib6_entry_type_set;
 7410
 7411	fib_entry->fib_node = fib_node;
 7412
 7413	return fib6_entry;
 7414
 7415err_fib6_entry_type_set:
 7416	mlxsw_sp_nexthop_group_vr_unlink(fib_entry->nh_group, fib_node->fib);
 7417err_nexthop_group_vr_link:
 7418	mlxsw_sp_nexthop6_group_put(mlxsw_sp, fib_entry);
 7419err_rt6_unwind:
 7420	for (; i > 0; i--) {
 7421		fib6_entry->nrt6--;
 7422		mlxsw_sp_rt6 = list_last_entry(&fib6_entry->rt6_list,
 7423					       struct mlxsw_sp_rt6, list);
 7424		list_del(&mlxsw_sp_rt6->list);
 7425		mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
 7426	}
 7427	kfree(fib6_entry);
 7428	return ERR_PTR(err);
 7429}
 7430
 7431static void
 7432mlxsw_sp_fib6_entry_type_unset(struct mlxsw_sp *mlxsw_sp,
 7433			       struct mlxsw_sp_fib6_entry *fib6_entry)
 7434{
 7435	mlxsw_sp_fib_entry_type_unset(mlxsw_sp, &fib6_entry->common);
 7436}
 7437
 7438static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp *mlxsw_sp,
 7439					struct mlxsw_sp_fib6_entry *fib6_entry)
 7440{
 7441	struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
 7442
 7443	mlxsw_sp_fib6_entry_type_unset(mlxsw_sp, fib6_entry);
 7444	mlxsw_sp_nexthop_group_vr_unlink(fib6_entry->common.nh_group,
 7445					 fib_node->fib);
 7446	mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
 7447	mlxsw_sp_fib6_entry_rt_destroy_all(fib6_entry);
 7448	WARN_ON(fib6_entry->nrt6);
 7449	kfree(fib6_entry);
 7450}
 7451
 7452static struct mlxsw_sp_fib6_entry *
 7453mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
 7454			   const struct fib6_info *rt)
 7455{
 7456	struct mlxsw_sp_fib6_entry *fib6_entry;
 7457	struct mlxsw_sp_fib_node *fib_node;
 7458	struct mlxsw_sp_fib *fib;
 7459	struct fib6_info *cmp_rt;
 7460	struct mlxsw_sp_vr *vr;
 7461
 7462	vr = mlxsw_sp_vr_find(mlxsw_sp, rt->fib6_table->tb6_id);
 7463	if (!vr)
 7464		return NULL;
 7465	fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV6);
 7466
 7467	fib_node = mlxsw_sp_fib_node_lookup(fib, &rt->fib6_dst.addr,
 7468					    sizeof(rt->fib6_dst.addr),
 7469					    rt->fib6_dst.plen);
 7470	if (!fib_node)
 7471		return NULL;
 7472
 7473	fib6_entry = container_of(fib_node->fib_entry,
 7474				  struct mlxsw_sp_fib6_entry, common);
 7475	cmp_rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
 7476	if (rt->fib6_table->tb6_id == cmp_rt->fib6_table->tb6_id &&
 7477	    rt->fib6_metric == cmp_rt->fib6_metric &&
 7478	    mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt))
 7479		return fib6_entry;
 7480
 7481	return NULL;
 7482}
 7483
 7484static bool mlxsw_sp_fib6_allow_replace(struct mlxsw_sp_fib6_entry *fib6_entry)
 7485{
 7486	struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
 7487	struct mlxsw_sp_fib6_entry *fib6_replaced;
 7488	struct fib6_info *rt, *rt_replaced;
 7489
 7490	if (!fib_node->fib_entry)
 7491		return true;
 7492
 7493	fib6_replaced = container_of(fib_node->fib_entry,
 7494				     struct mlxsw_sp_fib6_entry,
 7495				     common);
 7496	rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
 7497	rt_replaced = mlxsw_sp_fib6_entry_rt(fib6_replaced);
 7498	if (rt->fib6_table->tb6_id == RT_TABLE_MAIN &&
 7499	    rt_replaced->fib6_table->tb6_id == RT_TABLE_LOCAL)
 7500		return false;
 7501
 7502	return true;
 7503}
 7504
 7505static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
 7506					struct fib6_info **rt_arr,
 7507					unsigned int nrt6)
 7508{
 7509	struct mlxsw_sp_fib6_entry *fib6_entry, *fib6_replaced;
 7510	struct mlxsw_sp_fib_entry *replaced;
 7511	struct mlxsw_sp_fib_node *fib_node;
 7512	struct fib6_info *rt = rt_arr[0];
 7513	int err;
 7514
 7515	if (rt->fib6_src.plen)
 7516		return -EINVAL;
 7517
 7518	if (mlxsw_sp_fib6_rt_should_ignore(rt))
 7519		return 0;
 7520
 7521	if (rt->nh && !mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, rt->nh->id))
 7522		return 0;
 7523
 7524	fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->fib6_table->tb6_id,
 7525					 &rt->fib6_dst.addr,
 7526					 sizeof(rt->fib6_dst.addr),
 7527					 rt->fib6_dst.plen,
 7528					 MLXSW_SP_L3_PROTO_IPV6);
 7529	if (IS_ERR(fib_node))
 7530		return PTR_ERR(fib_node);
 7531
 7532	fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt_arr,
 7533						nrt6);
 7534	if (IS_ERR(fib6_entry)) {
 7535		err = PTR_ERR(fib6_entry);
 7536		goto err_fib6_entry_create;
 7537	}
 7538
 7539	if (!mlxsw_sp_fib6_allow_replace(fib6_entry)) {
 7540		mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
 7541		mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
 7542		return 0;
 7543	}
 7544
 7545	replaced = fib_node->fib_entry;
 7546	err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib6_entry->common);
 7547	if (err)
 7548		goto err_fib_node_entry_link;
 7549
 7550	/* Nothing to replace */
 7551	if (!replaced)
 7552		return 0;
 7553
 7554	mlxsw_sp_fib_entry_hw_flags_clear(mlxsw_sp, replaced);
 7555	fib6_replaced = container_of(replaced, struct mlxsw_sp_fib6_entry,
 7556				     common);
 7557	mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_replaced);
 7558
 7559	return 0;
 7560
 7561err_fib_node_entry_link:
 7562	fib_node->fib_entry = replaced;
 7563	mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
 7564err_fib6_entry_create:
 7565	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
 7566	return err;
 7567}
 7568
 7569static int mlxsw_sp_router_fib6_append(struct mlxsw_sp *mlxsw_sp,
 7570				       struct fib6_info **rt_arr,
 7571				       unsigned int nrt6)
 7572{
 7573	struct mlxsw_sp_fib6_entry *fib6_entry;
 7574	struct mlxsw_sp_fib_node *fib_node;
 7575	struct fib6_info *rt = rt_arr[0];
 7576	int err;
 7577
 7578	if (rt->fib6_src.plen)
 7579		return -EINVAL;
 7580
 7581	if (mlxsw_sp_fib6_rt_should_ignore(rt))
 7582		return 0;
 7583
 7584	fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->fib6_table->tb6_id,
 7585					 &rt->fib6_dst.addr,
 7586					 sizeof(rt->fib6_dst.addr),
 7587					 rt->fib6_dst.plen,
 7588					 MLXSW_SP_L3_PROTO_IPV6);
 7589	if (IS_ERR(fib_node))
 7590		return PTR_ERR(fib_node);
 7591
 7592	if (WARN_ON_ONCE(!fib_node->fib_entry)) {
 7593		mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
 7594		return -EINVAL;
 7595	}
 7596
 7597	fib6_entry = container_of(fib_node->fib_entry,
 7598				  struct mlxsw_sp_fib6_entry, common);
 7599	err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt_arr,
 7600					      nrt6);
 7601	if (err)
 7602		goto err_fib6_entry_nexthop_add;
 7603
 7604	return 0;
 7605
 7606err_fib6_entry_nexthop_add:
 7607	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
 7608	return err;
 7609}
 7610
 7611static void mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp,
 7612				     struct fib6_info **rt_arr,
 7613				     unsigned int nrt6)
 7614{
 7615	struct mlxsw_sp_fib6_entry *fib6_entry;
 7616	struct mlxsw_sp_fib_node *fib_node;
 7617	struct fib6_info *rt = rt_arr[0];
 7618
 7619	if (mlxsw_sp_fib6_rt_should_ignore(rt))
 7620		return;
 7621
 7622	/* Multipath routes are first added to the FIB trie and only then
 7623	 * notified. If we vetoed the addition, we will get a delete
 7624	 * notification for a route we do not have. Therefore, do not warn if
 7625	 * route was not found.
 7626	 */
 7627	fib6_entry = mlxsw_sp_fib6_entry_lookup(mlxsw_sp, rt);
 7628	if (!fib6_entry)
 7629		return;
 7630
 7631	/* If not all the nexthops are deleted, then only reduce the nexthop
 7632	 * group.
 7633	 */
 7634	if (nrt6 != fib6_entry->nrt6) {
 7635		mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp, fib6_entry, rt_arr,
 7636						nrt6);
 7637		return;
 7638	}
 7639
 7640	fib_node = fib6_entry->common.fib_node;
 7641
 7642	mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &fib6_entry->common);
 7643	mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
 7644	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
 7645}
 7646
 7647static struct mlxsw_sp_mr_table *
 7648mlxsw_sp_router_fibmr_family_to_table(struct mlxsw_sp_vr *vr, int family)
 7649{
 7650	if (family == RTNL_FAMILY_IPMR)
 7651		return vr->mr_table[MLXSW_SP_L3_PROTO_IPV4];
 7652	else
 7653		return vr->mr_table[MLXSW_SP_L3_PROTO_IPV6];
 7654}
 7655
 7656static int mlxsw_sp_router_fibmr_add(struct mlxsw_sp *mlxsw_sp,
 7657				     struct mfc_entry_notifier_info *men_info,
 7658				     bool replace)
 7659{
 7660	struct mlxsw_sp_mr_table *mrt;
 7661	struct mlxsw_sp_vr *vr;
 7662
 7663	vr = mlxsw_sp_vr_get(mlxsw_sp, men_info->tb_id, NULL);
 7664	if (IS_ERR(vr))
 7665		return PTR_ERR(vr);
 7666
 7667	mrt = mlxsw_sp_router_fibmr_family_to_table(vr, men_info->info.family);
 7668	return mlxsw_sp_mr_route_add(mrt, men_info->mfc, replace);
 7669}
 7670
 7671static void mlxsw_sp_router_fibmr_del(struct mlxsw_sp *mlxsw_sp,
 7672				      struct mfc_entry_notifier_info *men_info)
 7673{
 7674	struct mlxsw_sp_mr_table *mrt;
 7675	struct mlxsw_sp_vr *vr;
 7676
 7677	vr = mlxsw_sp_vr_find(mlxsw_sp, men_info->tb_id);
 7678	if (WARN_ON(!vr))
 7679		return;
 7680
 7681	mrt = mlxsw_sp_router_fibmr_family_to_table(vr, men_info->info.family);
 7682	mlxsw_sp_mr_route_del(mrt, men_info->mfc);
 7683	mlxsw_sp_vr_put(mlxsw_sp, vr);
 7684}
 7685
 7686static int
 7687mlxsw_sp_router_fibmr_vif_add(struct mlxsw_sp *mlxsw_sp,
 7688			      struct vif_entry_notifier_info *ven_info)
 7689{
 7690	struct mlxsw_sp_mr_table *mrt;
 7691	struct mlxsw_sp_rif *rif;
 7692	struct mlxsw_sp_vr *vr;
 7693
 7694	vr = mlxsw_sp_vr_get(mlxsw_sp, ven_info->tb_id, NULL);
 7695	if (IS_ERR(vr))
 7696		return PTR_ERR(vr);
 7697
 7698	mrt = mlxsw_sp_router_fibmr_family_to_table(vr, ven_info->info.family);
 7699	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, ven_info->dev);
 7700	return mlxsw_sp_mr_vif_add(mrt, ven_info->dev,
 7701				   ven_info->vif_index,
 7702				   ven_info->vif_flags, rif);
 7703}
 7704
 7705static void
 7706mlxsw_sp_router_fibmr_vif_del(struct mlxsw_sp *mlxsw_sp,
 7707			      struct vif_entry_notifier_info *ven_info)
 7708{
 7709	struct mlxsw_sp_mr_table *mrt;
 7710	struct mlxsw_sp_vr *vr;
 7711
 7712	vr = mlxsw_sp_vr_find(mlxsw_sp, ven_info->tb_id);
 7713	if (WARN_ON(!vr))
 7714		return;
 7715
 7716	mrt = mlxsw_sp_router_fibmr_family_to_table(vr, ven_info->info.family);
 7717	mlxsw_sp_mr_vif_del(mrt, ven_info->vif_index);
 7718	mlxsw_sp_vr_put(mlxsw_sp, vr);
 7719}
 7720
 7721static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp *mlxsw_sp,
 7722				     struct mlxsw_sp_fib_node *fib_node)
 7723{
 7724	struct mlxsw_sp_fib4_entry *fib4_entry;
 7725
 7726	fib4_entry = container_of(fib_node->fib_entry,
 7727				  struct mlxsw_sp_fib4_entry, common);
 7728	mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, fib_node->fib_entry);
 7729	mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
 7730	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
 7731}
 7732
 7733static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp *mlxsw_sp,
 7734				     struct mlxsw_sp_fib_node *fib_node)
 7735{
 7736	struct mlxsw_sp_fib6_entry *fib6_entry;
 7737
 7738	fib6_entry = container_of(fib_node->fib_entry,
 7739				  struct mlxsw_sp_fib6_entry, common);
 7740	mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, fib_node->fib_entry);
 7741	mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
 7742	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
 7743}
 7744
 7745static void mlxsw_sp_fib_node_flush(struct mlxsw_sp *mlxsw_sp,
 7746				    struct mlxsw_sp_fib_node *fib_node)
 7747{
 7748	switch (fib_node->fib->proto) {
 7749	case MLXSW_SP_L3_PROTO_IPV4:
 7750		mlxsw_sp_fib4_node_flush(mlxsw_sp, fib_node);
 7751		break;
 7752	case MLXSW_SP_L3_PROTO_IPV6:
 7753		mlxsw_sp_fib6_node_flush(mlxsw_sp, fib_node);
 7754		break;
 7755	}
 7756}
 7757
 7758static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp,
 7759				  struct mlxsw_sp_vr *vr,
 7760				  enum mlxsw_sp_l3proto proto)
 7761{
 7762	struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto);
 7763	struct mlxsw_sp_fib_node *fib_node, *tmp;
 7764
 7765	list_for_each_entry_safe(fib_node, tmp, &fib->node_list, list) {
 7766		bool do_break = &tmp->list == &fib->node_list;
 7767
 7768		mlxsw_sp_fib_node_flush(mlxsw_sp, fib_node);
 7769		if (do_break)
 7770			break;
 7771	}
 7772}
 7773
 7774static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp)
 7775{
 7776	int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
 7777	int i, j;
 7778
 7779	for (i = 0; i < max_vrs; i++) {
 7780		struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
 7781
 7782		if (!mlxsw_sp_vr_is_used(vr))
 7783			continue;
 7784
 7785		for (j = 0; j < MLXSW_SP_L3_PROTO_MAX; j++)
 7786			mlxsw_sp_mr_table_flush(vr->mr_table[j]);
 7787		mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4);
 7788
 7789		/* If virtual router was only used for IPv4, then it's no
 7790		 * longer used.
 7791		 */
 7792		if (!mlxsw_sp_vr_is_used(vr))
 7793			continue;
 7794		mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV6);
 7795	}
 7796}
 7797
 7798struct mlxsw_sp_fib6_event_work {
 7799	struct fib6_info **rt_arr;
 7800	unsigned int nrt6;
 7801};
 7802
 7803struct mlxsw_sp_fib_event_work {
 7804	struct work_struct work;
 7805	netdevice_tracker dev_tracker;
 7806	union {
 7807		struct mlxsw_sp_fib6_event_work fib6_work;
 7808		struct fib_entry_notifier_info fen_info;
 7809		struct fib_rule_notifier_info fr_info;
 7810		struct fib_nh_notifier_info fnh_info;
 7811		struct mfc_entry_notifier_info men_info;
 7812		struct vif_entry_notifier_info ven_info;
 7813	};
 7814	struct mlxsw_sp *mlxsw_sp;
 7815	unsigned long event;
 7816};
 7817
 7818static int
 7819mlxsw_sp_router_fib6_work_init(struct mlxsw_sp_fib6_event_work *fib6_work,
 7820			       struct fib6_entry_notifier_info *fen6_info)
 7821{
 7822	struct fib6_info *rt = fen6_info->rt;
 7823	struct fib6_info **rt_arr;
 7824	struct fib6_info *iter;
 7825	unsigned int nrt6;
 7826	int i = 0;
 7827
 7828	nrt6 = fen6_info->nsiblings + 1;
 7829
 7830	rt_arr = kcalloc(nrt6, sizeof(struct fib6_info *), GFP_ATOMIC);
 7831	if (!rt_arr)
 7832		return -ENOMEM;
 7833
 7834	fib6_work->rt_arr = rt_arr;
 7835	fib6_work->nrt6 = nrt6;
 7836
 7837	rt_arr[0] = rt;
 7838	fib6_info_hold(rt);
 7839
 7840	if (!fen6_info->nsiblings)
 7841		return 0;
 7842
 7843	list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) {
 7844		if (i == fen6_info->nsiblings)
 7845			break;
 7846
 7847		rt_arr[i + 1] = iter;
 7848		fib6_info_hold(iter);
 7849		i++;
 7850	}
 7851	WARN_ON_ONCE(i != fen6_info->nsiblings);
 7852
 7853	return 0;
 7854}
 7855
 7856static void
 7857mlxsw_sp_router_fib6_work_fini(struct mlxsw_sp_fib6_event_work *fib6_work)
 7858{
 7859	int i;
 7860
 7861	for (i = 0; i < fib6_work->nrt6; i++)
 7862		mlxsw_sp_rt6_release(fib6_work->rt_arr[i]);
 7863	kfree(fib6_work->rt_arr);
 7864}
 7865
 7866static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
 7867{
 7868	struct mlxsw_sp_fib_event_work *fib_work =
 7869		container_of(work, struct mlxsw_sp_fib_event_work, work);
 7870	struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
 7871	int err;
 7872
 7873	mutex_lock(&mlxsw_sp->router->lock);
 7874	mlxsw_sp_span_respin(mlxsw_sp);
 7875
 7876	switch (fib_work->event) {
 7877	case FIB_EVENT_ENTRY_REPLACE:
 7878		err = mlxsw_sp_router_fib4_replace(mlxsw_sp,
 7879						   &fib_work->fen_info);
 7880		if (err) {
 7881			dev_warn(mlxsw_sp->bus_info->dev, "FIB replace failed.\n");
 7882			mlxsw_sp_fib4_offload_failed_flag_set(mlxsw_sp,
 7883							      &fib_work->fen_info);
 7884		}
 7885		fib_info_put(fib_work->fen_info.fi);
 7886		break;
 7887	case FIB_EVENT_ENTRY_DEL:
 7888		mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info);
 7889		fib_info_put(fib_work->fen_info.fi);
 7890		break;
 7891	case FIB_EVENT_NH_ADD:
 7892	case FIB_EVENT_NH_DEL:
 7893		mlxsw_sp_nexthop4_event(mlxsw_sp, fib_work->event,
 7894					fib_work->fnh_info.fib_nh);
 7895		fib_info_put(fib_work->fnh_info.fib_nh->nh_parent);
 7896		break;
 7897	}
 7898	mutex_unlock(&mlxsw_sp->router->lock);
 7899	kfree(fib_work);
 7900}
 7901
 7902static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
 7903{
 7904	struct mlxsw_sp_fib_event_work *fib_work =
 7905		    container_of(work, struct mlxsw_sp_fib_event_work, work);
 7906	struct mlxsw_sp_fib6_event_work *fib6_work = &fib_work->fib6_work;
 7907	struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
 7908	int err;
 7909
 7910	mutex_lock(&mlxsw_sp->router->lock);
 7911	mlxsw_sp_span_respin(mlxsw_sp);
 7912
 7913	switch (fib_work->event) {
 7914	case FIB_EVENT_ENTRY_REPLACE:
 7915		err = mlxsw_sp_router_fib6_replace(mlxsw_sp,
 7916						   fib6_work->rt_arr,
 7917						   fib6_work->nrt6);
 7918		if (err) {
 7919			dev_warn(mlxsw_sp->bus_info->dev, "FIB replace failed.\n");
 7920			mlxsw_sp_fib6_offload_failed_flag_set(mlxsw_sp,
 7921							      fib6_work->rt_arr,
 7922							      fib6_work->nrt6);
 7923		}
 7924		mlxsw_sp_router_fib6_work_fini(fib6_work);
 7925		break;
 7926	case FIB_EVENT_ENTRY_APPEND:
 7927		err = mlxsw_sp_router_fib6_append(mlxsw_sp,
 7928						  fib6_work->rt_arr,
 7929						  fib6_work->nrt6);
 7930		if (err) {
 7931			dev_warn(mlxsw_sp->bus_info->dev, "FIB append failed.\n");
 7932			mlxsw_sp_fib6_offload_failed_flag_set(mlxsw_sp,
 7933							      fib6_work->rt_arr,
 7934							      fib6_work->nrt6);
 7935		}
 7936		mlxsw_sp_router_fib6_work_fini(fib6_work);
 7937		break;
 7938	case FIB_EVENT_ENTRY_DEL:
 7939		mlxsw_sp_router_fib6_del(mlxsw_sp,
 7940					 fib6_work->rt_arr,
 7941					 fib6_work->nrt6);
 7942		mlxsw_sp_router_fib6_work_fini(fib6_work);
 7943		break;
 7944	}
 7945	mutex_unlock(&mlxsw_sp->router->lock);
 7946	kfree(fib_work);
 7947}
 7948
 7949static void mlxsw_sp_router_fibmr_event_work(struct work_struct *work)
 7950{
 7951	struct mlxsw_sp_fib_event_work *fib_work =
 7952		container_of(work, struct mlxsw_sp_fib_event_work, work);
 7953	struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
 7954	bool replace;
 7955	int err;
 7956
 7957	rtnl_lock();
 7958	mutex_lock(&mlxsw_sp->router->lock);
 7959	switch (fib_work->event) {
 7960	case FIB_EVENT_ENTRY_REPLACE:
 7961	case FIB_EVENT_ENTRY_ADD:
 7962		replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
 7963
 7964		err = mlxsw_sp_router_fibmr_add(mlxsw_sp, &fib_work->men_info,
 7965						replace);
 7966		if (err)
 7967			dev_warn(mlxsw_sp->bus_info->dev, "MR entry add failed.\n");
 7968		mr_cache_put(fib_work->men_info.mfc);
 7969		break;
 7970	case FIB_EVENT_ENTRY_DEL:
 7971		mlxsw_sp_router_fibmr_del(mlxsw_sp, &fib_work->men_info);
 7972		mr_cache_put(fib_work->men_info.mfc);
 7973		break;
 7974	case FIB_EVENT_VIF_ADD:
 7975		err = mlxsw_sp_router_fibmr_vif_add(mlxsw_sp,
 7976						    &fib_work->ven_info);
 7977		if (err)
 7978			dev_warn(mlxsw_sp->bus_info->dev, "MR VIF add failed.\n");
 7979		netdev_put(fib_work->ven_info.dev, &fib_work->dev_tracker);
 7980		break;
 7981	case FIB_EVENT_VIF_DEL:
 7982		mlxsw_sp_router_fibmr_vif_del(mlxsw_sp,
 7983					      &fib_work->ven_info);
 7984		netdev_put(fib_work->ven_info.dev, &fib_work->dev_tracker);
 7985		break;
 7986	}
 7987	mutex_unlock(&mlxsw_sp->router->lock);
 7988	rtnl_unlock();
 7989	kfree(fib_work);
 7990}
 7991
 7992static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work,
 7993				       struct fib_notifier_info *info)
 7994{
 7995	struct fib_entry_notifier_info *fen_info;
 7996	struct fib_nh_notifier_info *fnh_info;
 7997
 7998	switch (fib_work->event) {
 7999	case FIB_EVENT_ENTRY_REPLACE:
 8000	case FIB_EVENT_ENTRY_DEL:
 8001		fen_info = container_of(info, struct fib_entry_notifier_info,
 8002					info);
 8003		fib_work->fen_info = *fen_info;
 8004		/* Take reference on fib_info to prevent it from being
 8005		 * freed while work is queued. Release it afterwards.
 8006		 */
 8007		fib_info_hold(fib_work->fen_info.fi);
 8008		break;
 8009	case FIB_EVENT_NH_ADD:
 8010	case FIB_EVENT_NH_DEL:
 8011		fnh_info = container_of(info, struct fib_nh_notifier_info,
 8012					info);
 8013		fib_work->fnh_info = *fnh_info;
 8014		fib_info_hold(fib_work->fnh_info.fib_nh->nh_parent);
 8015		break;
 8016	}
 8017}
 8018
 8019static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
 8020				      struct fib_notifier_info *info)
 8021{
 8022	struct fib6_entry_notifier_info *fen6_info;
 8023	int err;
 8024
 8025	switch (fib_work->event) {
 8026	case FIB_EVENT_ENTRY_REPLACE:
 8027	case FIB_EVENT_ENTRY_APPEND:
 8028	case FIB_EVENT_ENTRY_DEL:
 8029		fen6_info = container_of(info, struct fib6_entry_notifier_info,
 8030					 info);
 8031		err = mlxsw_sp_router_fib6_work_init(&fib_work->fib6_work,
 8032						     fen6_info);
 8033		if (err)
 8034			return err;
 8035		break;
 8036	}
 8037
 8038	return 0;
 8039}
 8040
 8041static void
 8042mlxsw_sp_router_fibmr_event(struct mlxsw_sp_fib_event_work *fib_work,
 8043			    struct fib_notifier_info *info)
 8044{
 8045	switch (fib_work->event) {
 8046	case FIB_EVENT_ENTRY_REPLACE:
 8047	case FIB_EVENT_ENTRY_ADD:
 8048	case FIB_EVENT_ENTRY_DEL:
 8049		memcpy(&fib_work->men_info, info, sizeof(fib_work->men_info));
 8050		mr_cache_hold(fib_work->men_info.mfc);
 8051		break;
 8052	case FIB_EVENT_VIF_ADD:
 8053	case FIB_EVENT_VIF_DEL:
 8054		memcpy(&fib_work->ven_info, info, sizeof(fib_work->ven_info));
 8055		netdev_hold(fib_work->ven_info.dev, &fib_work->dev_tracker,
 8056			    GFP_ATOMIC);
 8057		break;
 8058	}
 8059}
 8060
 8061static int mlxsw_sp_router_fib_rule_event(unsigned long event,
 8062					  struct fib_notifier_info *info,
 8063					  struct mlxsw_sp *mlxsw_sp)
 8064{
 8065	struct netlink_ext_ack *extack = info->extack;
 8066	struct fib_rule_notifier_info *fr_info;
 8067	struct fib_rule *rule;
 8068	int err = 0;
 8069
 8070	/* nothing to do at the moment */
 8071	if (event == FIB_EVENT_RULE_DEL)
 8072		return 0;
 8073
 8074	fr_info = container_of(info, struct fib_rule_notifier_info, info);
 8075	rule = fr_info->rule;
 8076
 8077	/* Rule only affects locally generated traffic */
 8078	if (rule->iifindex == mlxsw_sp_net(mlxsw_sp)->loopback_dev->ifindex)
 8079		return 0;
 8080
 8081	switch (info->family) {
 8082	case AF_INET:
 8083		if (!fib4_rule_default(rule) && !rule->l3mdev)
 8084			err = -EOPNOTSUPP;
 8085		break;
 8086	case AF_INET6:
 8087		if (!fib6_rule_default(rule) && !rule->l3mdev)
 8088			err = -EOPNOTSUPP;
 8089		break;
 8090	case RTNL_FAMILY_IPMR:
 8091		if (!ipmr_rule_default(rule) && !rule->l3mdev)
 8092			err = -EOPNOTSUPP;
 8093		break;
 8094	case RTNL_FAMILY_IP6MR:
 8095		if (!ip6mr_rule_default(rule) && !rule->l3mdev)
 8096			err = -EOPNOTSUPP;
 8097		break;
 8098	}
 8099
 8100	if (err < 0)
 8101		NL_SET_ERR_MSG_MOD(extack, "FIB rules not supported");
 8102
 8103	return err;
 8104}
 8105
 8106/* Called with rcu_read_lock() */
 8107static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
 8108				     unsigned long event, void *ptr)
 8109{
 8110	struct mlxsw_sp_fib_event_work *fib_work;
 8111	struct fib_notifier_info *info = ptr;
 8112	struct mlxsw_sp_router *router;
 8113	int err;
 8114
 8115	if ((info->family != AF_INET && info->family != AF_INET6 &&
 8116	     info->family != RTNL_FAMILY_IPMR &&
 8117	     info->family != RTNL_FAMILY_IP6MR))
 8118		return NOTIFY_DONE;
 8119
 8120	router = container_of(nb, struct mlxsw_sp_router, fib_nb);
 8121
 8122	switch (event) {
 8123	case FIB_EVENT_RULE_ADD:
 8124	case FIB_EVENT_RULE_DEL:
 8125		err = mlxsw_sp_router_fib_rule_event(event, info,
 8126						     router->mlxsw_sp);
 8127		return notifier_from_errno(err);
 8128	case FIB_EVENT_ENTRY_ADD:
 8129	case FIB_EVENT_ENTRY_REPLACE:
 8130	case FIB_EVENT_ENTRY_APPEND:
 8131		if (info->family == AF_INET) {
 8132			struct fib_entry_notifier_info *fen_info = ptr;
 8133
 8134			if (fen_info->fi->fib_nh_is_v6) {
 8135				NL_SET_ERR_MSG_MOD(info->extack, "IPv6 gateway with IPv4 route is not supported");
 8136				return notifier_from_errno(-EINVAL);
 8137			}
 8138		}
 8139		break;
 8140	}
 8141
 8142	fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
 8143	if (!fib_work)
 8144		return NOTIFY_BAD;
 8145
 8146	fib_work->mlxsw_sp = router->mlxsw_sp;
 8147	fib_work->event = event;
 8148
 8149	switch (info->family) {
 8150	case AF_INET:
 8151		INIT_WORK(&fib_work->work, mlxsw_sp_router_fib4_event_work);
 8152		mlxsw_sp_router_fib4_event(fib_work, info);
 8153		break;
 8154	case AF_INET6:
 8155		INIT_WORK(&fib_work->work, mlxsw_sp_router_fib6_event_work);
 8156		err = mlxsw_sp_router_fib6_event(fib_work, info);
 8157		if (err)
 8158			goto err_fib_event;
 8159		break;
 8160	case RTNL_FAMILY_IP6MR:
 8161	case RTNL_FAMILY_IPMR:
 8162		INIT_WORK(&fib_work->work, mlxsw_sp_router_fibmr_event_work);
 8163		mlxsw_sp_router_fibmr_event(fib_work, info);
 8164		break;
 8165	}
 8166
 8167	mlxsw_core_schedule_work(&fib_work->work);
 8168
 8169	return NOTIFY_DONE;
 8170
 8171err_fib_event:
 8172	kfree(fib_work);
 8173	return NOTIFY_BAD;
 8174}
 8175
 8176static struct mlxsw_sp_rif *
 8177mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
 8178			 const struct net_device *dev)
 8179{
 8180	int max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
 8181	int i;
 8182
 8183	for (i = 0; i < max_rifs; i++)
 8184		if (mlxsw_sp->router->rifs[i] &&
 8185		    mlxsw_sp_rif_dev_is(mlxsw_sp->router->rifs[i], dev))
 8186			return mlxsw_sp->router->rifs[i];
 8187
 8188	return NULL;
 8189}
 8190
 8191static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif)
 8192{
 8193	char ritr_pl[MLXSW_REG_RITR_LEN];
 8194	int err;
 8195
 8196	mlxsw_reg_ritr_rif_pack(ritr_pl, rif);
 8197	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
 8198	if (err)
 8199		return err;
 8200
 8201	mlxsw_reg_ritr_enable_set(ritr_pl, false);
 8202	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
 8203}
 8204
 8205static int mlxsw_sp_router_rif_made_sync(struct mlxsw_sp *mlxsw_sp,
 8206					 struct mlxsw_sp_rif *rif)
 8207{
 8208	int err;
 8209
 8210	err = mlxsw_sp_neigh_rif_made_sync(mlxsw_sp, rif);
 8211	if (err)
 8212		return err;
 8213
 8214	err = mlxsw_sp_nexthop_rif_made_sync(mlxsw_sp, rif);
 8215	if (err)
 8216		goto err_nexthop;
 8217
 8218	return 0;
 8219
 8220err_nexthop:
 8221	mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif);
 8222	return err;
 8223}
 8224
 8225static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
 8226					  struct mlxsw_sp_rif *rif)
 8227{
 8228	/* Signal to nexthop cleanup that the RIF is going away. */
 8229	rif->crif->rif = NULL;
 8230
 8231	mlxsw_sp_router_rif_disable(mlxsw_sp, rif->rif_index);
 8232	mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp, rif);
 8233	mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif);
 8234}
 8235
 8236static bool __mlxsw_sp_dev_addr_list_empty(const struct net_device *dev)
 8237{
 8238	struct inet6_dev *inet6_dev;
 8239	struct in_device *idev;
 8240
 8241	idev = __in_dev_get_rcu(dev);
 8242	if (idev && idev->ifa_list)
 8243		return false;
 8244
 8245	inet6_dev = __in6_dev_get(dev);
 8246	if (inet6_dev && !list_empty(&inet6_dev->addr_list))
 8247		return false;
 8248
 8249	return true;
 8250}
 8251
 8252static bool mlxsw_sp_dev_addr_list_empty(const struct net_device *dev)
 8253{
 8254	bool addr_list_empty;
 8255
 8256	rcu_read_lock();
 8257	addr_list_empty = __mlxsw_sp_dev_addr_list_empty(dev);
 8258	rcu_read_unlock();
 8259
 8260	return addr_list_empty;
 8261}
 8262
 8263static bool
 8264mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev,
 8265			   unsigned long event)
 8266{
 8267	bool addr_list_empty;
 8268
 8269	switch (event) {
 8270	case NETDEV_UP:
 8271		return rif == NULL;
 8272	case NETDEV_DOWN:
 8273		addr_list_empty = mlxsw_sp_dev_addr_list_empty(dev);
 8274
 8275		/* macvlans do not have a RIF, but rather piggy back on the
 8276		 * RIF of their lower device.
 8277		 */
 8278		if (netif_is_macvlan(dev) && addr_list_empty)
 8279			return true;
 8280
 8281		if (rif && addr_list_empty &&
 8282		    !netif_is_l3_slave(mlxsw_sp_rif_dev(rif)))
 8283			return true;
 8284		/* It is possible we already removed the RIF ourselves
 8285		 * if it was assigned to a netdev that is now a bridge
 8286		 * or LAG slave.
 8287		 */
 8288		return false;
 8289	}
 8290
 8291	return false;
 8292}
 8293
 8294static enum mlxsw_sp_rif_type
 8295mlxsw_sp_dev_rif_type(const struct mlxsw_sp *mlxsw_sp,
 8296		      const struct net_device *dev)
 8297{
 8298	enum mlxsw_sp_fid_type type;
 8299
 8300	if (mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL))
 8301		return MLXSW_SP_RIF_TYPE_IPIP_LB;
 8302
 8303	/* Otherwise RIF type is derived from the type of the underlying FID. */
 8304	if (is_vlan_dev(dev) && netif_is_bridge_master(vlan_dev_real_dev(dev)))
 8305		type = MLXSW_SP_FID_TYPE_8021Q;
 8306	else if (netif_is_bridge_master(dev) && br_vlan_enabled(dev))
 8307		type = MLXSW_SP_FID_TYPE_8021Q;
 8308	else if (netif_is_bridge_master(dev))
 8309		type = MLXSW_SP_FID_TYPE_8021D;
 8310	else
 8311		type = MLXSW_SP_FID_TYPE_RFID;
 8312
 8313	return mlxsw_sp_fid_type_rif_type(mlxsw_sp, type);
 8314}
 8315
 8316static int mlxsw_sp_rif_index_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_rif_index,
 8317				    u8 rif_entries)
 8318{
 8319	*p_rif_index = gen_pool_alloc(mlxsw_sp->router->rifs_table,
 8320				      rif_entries);
 8321	if (*p_rif_index == 0)
 8322		return -ENOBUFS;
 8323	*p_rif_index -= MLXSW_SP_ROUTER_GENALLOC_OFFSET;
 8324
 8325	/* RIF indexes must be aligned to the allocation size. */
 8326	WARN_ON_ONCE(*p_rif_index % rif_entries);
 8327
 8328	return 0;
 8329}
 8330
 8331static void mlxsw_sp_rif_index_free(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
 8332				    u8 rif_entries)
 8333{
 8334	gen_pool_free(mlxsw_sp->router->rifs_table,
 8335		      MLXSW_SP_ROUTER_GENALLOC_OFFSET + rif_index, rif_entries);
 8336}
 8337
 8338static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
 8339					       u16 vr_id,
 8340					       struct mlxsw_sp_crif *crif)
 8341{
 8342	struct net_device *l3_dev = crif ? crif->key.dev : NULL;
 8343	struct mlxsw_sp_rif *rif;
 8344
 8345	rif = kzalloc(rif_size, GFP_KERNEL);
 8346	if (!rif)
 8347		return NULL;
 8348
 8349	INIT_LIST_HEAD(&rif->neigh_list);
 8350	if (l3_dev) {
 8351		ether_addr_copy(rif->addr, l3_dev->dev_addr);
 8352		rif->mtu = l3_dev->mtu;
 8353	}
 8354	rif->vr_id = vr_id;
 8355	rif->rif_index = rif_index;
 8356	if (crif) {
 8357		rif->crif = crif;
 8358		crif->rif = rif;
 8359	}
 8360
 8361	return rif;
 8362}
 8363
 8364static void mlxsw_sp_rif_free(struct mlxsw_sp_rif *rif)
 8365{
 8366	WARN_ON(!list_empty(&rif->neigh_list));
 8367
 8368	if (rif->crif)
 8369		rif->crif->rif = NULL;
 8370	kfree(rif);
 8371}
 8372
 8373struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp,
 8374					   u16 rif_index)
 8375{
 8376	return mlxsw_sp->router->rifs[rif_index];
 8377}
 8378
 8379u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif)
 8380{
 8381	return rif->rif_index;
 8382}
 8383
 8384u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
 8385{
 8386	return lb_rif->common.rif_index;
 8387}
 8388
 8389u16 mlxsw_sp_ipip_lb_ul_rif_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
 8390{
 8391	return lb_rif->ul_rif_id;
 8392}
 8393
 8394static bool
 8395mlxsw_sp_router_port_l3_stats_enabled(struct mlxsw_sp_rif *rif)
 8396{
 8397	return mlxsw_sp_rif_counter_valid_get(rif,
 8398					      MLXSW_SP_RIF_COUNTER_EGRESS) &&
 8399	       mlxsw_sp_rif_counter_valid_get(rif,
 8400					      MLXSW_SP_RIF_COUNTER_INGRESS);
 8401}
 8402
 8403static int
 8404mlxsw_sp_router_port_l3_stats_enable(struct mlxsw_sp_rif *rif)
 8405{
 8406	int err;
 8407
 8408	err = mlxsw_sp_rif_counter_alloc(rif, MLXSW_SP_RIF_COUNTER_INGRESS);
 8409	if (err)
 8410		return err;
 8411
 8412	/* Clear stale data. */
 8413	err = mlxsw_sp_rif_counter_fetch_clear(rif,
 8414					       MLXSW_SP_RIF_COUNTER_INGRESS,
 8415					       NULL);
 8416	if (err)
 8417		goto err_clear_ingress;
 8418
 8419	err = mlxsw_sp_rif_counter_alloc(rif, MLXSW_SP_RIF_COUNTER_EGRESS);
 8420	if (err)
 8421		goto err_alloc_egress;
 8422
 8423	/* Clear stale data. */
 8424	err = mlxsw_sp_rif_counter_fetch_clear(rif,
 8425					       MLXSW_SP_RIF_COUNTER_EGRESS,
 8426					       NULL);
 8427	if (err)
 8428		goto err_clear_egress;
 8429
 8430	return 0;
 8431
 8432err_clear_egress:
 8433	mlxsw_sp_rif_counter_free(rif, MLXSW_SP_RIF_COUNTER_EGRESS);
 8434err_alloc_egress:
 8435err_clear_ingress:
 8436	mlxsw_sp_rif_counter_free(rif, MLXSW_SP_RIF_COUNTER_INGRESS);
 8437	return err;
 8438}
 8439
 8440static void
 8441mlxsw_sp_router_port_l3_stats_disable(struct mlxsw_sp_rif *rif)
 8442{
 8443	mlxsw_sp_rif_counter_free(rif, MLXSW_SP_RIF_COUNTER_EGRESS);
 8444	mlxsw_sp_rif_counter_free(rif, MLXSW_SP_RIF_COUNTER_INGRESS);
 8445}
 8446
 8447static void
 8448mlxsw_sp_router_port_l3_stats_report_used(struct mlxsw_sp_rif *rif,
 8449					  struct netdev_notifier_offload_xstats_info *info)
 8450{
 8451	if (!mlxsw_sp_router_port_l3_stats_enabled(rif))
 8452		return;
 8453	netdev_offload_xstats_report_used(info->report_used);
 8454}
 8455
 8456static int
 8457mlxsw_sp_router_port_l3_stats_fetch(struct mlxsw_sp_rif *rif,
 8458				    struct rtnl_hw_stats64 *p_stats)
 8459{
 8460	struct mlxsw_sp_rif_counter_set_basic ingress;
 8461	struct mlxsw_sp_rif_counter_set_basic egress;
 8462	int err;
 8463
 8464	err = mlxsw_sp_rif_counter_fetch_clear(rif,
 8465					       MLXSW_SP_RIF_COUNTER_INGRESS,
 8466					       &ingress);
 8467	if (err)
 8468		return err;
 8469
 8470	err = mlxsw_sp_rif_counter_fetch_clear(rif,
 8471					       MLXSW_SP_RIF_COUNTER_EGRESS,
 8472					       &egress);
 8473	if (err)
 8474		return err;
 8475
 8476#define MLXSW_SP_ROUTER_ALL_GOOD(SET, SFX)		\
 8477		((SET.good_unicast_ ## SFX) +		\
 8478		 (SET.good_multicast_ ## SFX) +		\
 8479		 (SET.good_broadcast_ ## SFX))
 8480
 8481	p_stats->rx_packets = MLXSW_SP_ROUTER_ALL_GOOD(ingress, packets);
 8482	p_stats->tx_packets = MLXSW_SP_ROUTER_ALL_GOOD(egress, packets);
 8483	p_stats->rx_bytes = MLXSW_SP_ROUTER_ALL_GOOD(ingress, bytes);
 8484	p_stats->tx_bytes = MLXSW_SP_ROUTER_ALL_GOOD(egress, bytes);
 8485	p_stats->rx_errors = ingress.error_packets;
 8486	p_stats->tx_errors = egress.error_packets;
 8487	p_stats->rx_dropped = ingress.discard_packets;
 8488	p_stats->tx_dropped = egress.discard_packets;
 8489	p_stats->multicast = ingress.good_multicast_packets +
 8490			     ingress.good_broadcast_packets;
 8491
 8492#undef MLXSW_SP_ROUTER_ALL_GOOD
 8493
 8494	return 0;
 8495}
 8496
 8497static int
 8498mlxsw_sp_router_port_l3_stats_report_delta(struct mlxsw_sp_rif *rif,
 8499					   struct netdev_notifier_offload_xstats_info *info)
 8500{
 8501	struct rtnl_hw_stats64 stats = {};
 8502	int err;
 8503
 8504	if (!mlxsw_sp_router_port_l3_stats_enabled(rif))
 8505		return 0;
 8506
 8507	err = mlxsw_sp_router_port_l3_stats_fetch(rif, &stats);
 8508	if (err)
 8509		return err;
 8510
 8511	netdev_offload_xstats_report_delta(info->report_delta, &stats);
 8512	return 0;
 8513}
 8514
 8515struct mlxsw_sp_router_hwstats_notify_work {
 8516	struct work_struct work;
 8517	struct net_device *dev;
 8518	netdevice_tracker dev_tracker;
 8519};
 8520
 8521static void mlxsw_sp_router_hwstats_notify_work(struct work_struct *work)
 8522{
 8523	struct mlxsw_sp_router_hwstats_notify_work *hws_work =
 8524		container_of(work, struct mlxsw_sp_router_hwstats_notify_work,
 8525			     work);
 8526
 8527	rtnl_lock();
 8528	rtnl_offload_xstats_notify(hws_work->dev);
 8529	rtnl_unlock();
 8530	netdev_put(hws_work->dev, &hws_work->dev_tracker);
 8531	kfree(hws_work);
 8532}
 8533
 8534static void
 8535mlxsw_sp_router_hwstats_notify_schedule(struct net_device *dev)
 8536{
 8537	struct mlxsw_sp_router_hwstats_notify_work *hws_work;
 8538
 8539	/* To collect notification payload, the core ends up sending another
 8540	 * notifier block message, which would deadlock on the attempt to
 8541	 * acquire the router lock again. Just postpone the notification until
 8542	 * later.
 8543	 */
 8544
 8545	hws_work = kzalloc(sizeof(*hws_work), GFP_KERNEL);
 8546	if (!hws_work)
 8547		return;
 8548
 8549	INIT_WORK(&hws_work->work, mlxsw_sp_router_hwstats_notify_work);
 8550	netdev_hold(dev, &hws_work->dev_tracker, GFP_KERNEL);
 8551	hws_work->dev = dev;
 8552	mlxsw_core_schedule_work(&hws_work->work);
 8553}
 8554
 8555int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif)
 8556{
 8557	return mlxsw_sp_rif_dev(rif)->ifindex;
 8558}
 8559
 8560bool mlxsw_sp_rif_has_dev(const struct mlxsw_sp_rif *rif)
 8561{
 8562	return !!mlxsw_sp_rif_dev(rif);
 8563}
 8564
 8565bool mlxsw_sp_rif_dev_is(const struct mlxsw_sp_rif *rif,
 8566			 const struct net_device *dev)
 8567{
 8568	return mlxsw_sp_rif_dev(rif) == dev;
 8569}
 8570
 8571static void mlxsw_sp_rif_push_l3_stats(struct mlxsw_sp_rif *rif)
 8572{
 8573	struct rtnl_hw_stats64 stats = {};
 8574
 8575	if (!mlxsw_sp_router_port_l3_stats_fetch(rif, &stats))
 8576		netdev_offload_xstats_push_delta(mlxsw_sp_rif_dev(rif),
 8577						 NETDEV_OFFLOAD_XSTATS_TYPE_L3,
 8578						 &stats);
 8579}
 8580
 8581static struct mlxsw_sp_rif *
 8582mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
 8583		    const struct mlxsw_sp_rif_params *params,
 8584		    struct netlink_ext_ack *extack)
 8585{
 8586	u8 rif_entries = params->double_entry ? 2 : 1;
 8587	u32 tb_id = l3mdev_fib_table(params->dev);
 8588	const struct mlxsw_sp_rif_ops *ops;
 8589	struct mlxsw_sp_fid *fid = NULL;
 8590	enum mlxsw_sp_rif_type type;
 8591	struct mlxsw_sp_crif *crif;
 8592	struct mlxsw_sp_rif *rif;
 8593	struct mlxsw_sp_vr *vr;
 8594	u16 rif_index;
 8595	int i, err;
 8596
 8597	type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev);
 8598	ops = mlxsw_sp->router->rif_ops_arr[type];
 8599
 8600	vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN, extack);
 8601	if (IS_ERR(vr))
 8602		return ERR_CAST(vr);
 8603	vr->rif_count++;
 8604
 8605	err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index, rif_entries);
 8606	if (err) {
 8607		NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported router interfaces");
 8608		goto err_rif_index_alloc;
 8609	}
 8610
 8611	crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, params->dev);
 8612	if (WARN_ON(!crif)) {
 8613		err = -ENOENT;
 8614		goto err_crif_lookup;
 8615	}
 8616
 8617	rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, crif);
 8618	if (!rif) {
 8619		err = -ENOMEM;
 8620		goto err_rif_alloc;
 8621	}
 8622	netdev_hold(params->dev, &rif->dev_tracker, GFP_KERNEL);
 8623	mlxsw_sp->router->rifs[rif_index] = rif;
 8624	rif->mlxsw_sp = mlxsw_sp;
 8625	rif->ops = ops;
 8626	rif->rif_entries = rif_entries;
 8627
 8628	if (ops->setup)
 8629		ops->setup(rif, params);
 8630
 8631	if (ops->fid_get) {
 8632		fid = ops->fid_get(rif, params, extack);
 8633		if (IS_ERR(fid)) {
 8634			err = PTR_ERR(fid);
 8635			goto err_fid_get;
 8636		}
 8637		rif->fid = fid;
 8638	}
 8639
 8640	err = ops->configure(rif, extack);
 8641	if (err)
 8642		goto err_configure;
 8643
 8644	for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++) {
 8645		err = mlxsw_sp_mr_rif_add(vr->mr_table[i], rif);
 8646		if (err)
 8647			goto err_mr_rif_add;
 8648	}
 8649
 8650	err = mlxsw_sp_router_rif_made_sync(mlxsw_sp, rif);
 8651	if (err)
 8652		goto err_rif_made_sync;
 8653
 8654	if (netdev_offload_xstats_enabled(params->dev,
 8655					  NETDEV_OFFLOAD_XSTATS_TYPE_L3)) {
 8656		err = mlxsw_sp_router_port_l3_stats_enable(rif);
 8657		if (err)
 8658			goto err_stats_enable;
 8659		mlxsw_sp_router_hwstats_notify_schedule(params->dev);
 8660	} else {
 8661		mlxsw_sp_rif_counters_alloc(rif);
 8662	}
 8663
 8664	atomic_add(rif_entries, &mlxsw_sp->router->rifs_count);
 8665	return rif;
 8666
 8667err_stats_enable:
 8668	mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
 8669err_rif_made_sync:
 8670err_mr_rif_add:
 8671	for (i--; i >= 0; i--)
 8672		mlxsw_sp_mr_rif_del(vr->mr_table[i], rif);
 8673	ops->deconfigure(rif);
 8674err_configure:
 8675	if (fid)
 8676		mlxsw_sp_fid_put(fid);
 8677err_fid_get:
 8678	mlxsw_sp->router->rifs[rif_index] = NULL;
 8679	netdev_put(params->dev, &rif->dev_tracker);
 8680	mlxsw_sp_rif_free(rif);
 8681err_rif_alloc:
 8682err_crif_lookup:
 8683	mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
 8684err_rif_index_alloc:
 8685	vr->rif_count--;
 8686	mlxsw_sp_vr_put(mlxsw_sp, vr);
 8687	return ERR_PTR(err);
 8688}
 8689
 8690static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
 8691{
 8692	struct net_device *dev = mlxsw_sp_rif_dev(rif);
 8693	const struct mlxsw_sp_rif_ops *ops = rif->ops;
 8694	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
 8695	struct mlxsw_sp_crif *crif = rif->crif;
 8696	struct mlxsw_sp_fid *fid = rif->fid;
 8697	u8 rif_entries = rif->rif_entries;
 8698	u16 rif_index = rif->rif_index;
 8699	struct mlxsw_sp_vr *vr;
 8700	int i;
 8701
 8702	atomic_sub(rif_entries, &mlxsw_sp->router->rifs_count);
 8703	mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
 8704	vr = &mlxsw_sp->router->vrs[rif->vr_id];
 8705
 8706	if (netdev_offload_xstats_enabled(dev, NETDEV_OFFLOAD_XSTATS_TYPE_L3)) {
 8707		mlxsw_sp_rif_push_l3_stats(rif);
 8708		mlxsw_sp_router_port_l3_stats_disable(rif);
 8709		mlxsw_sp_router_hwstats_notify_schedule(dev);
 8710	} else {
 8711		mlxsw_sp_rif_counters_free(rif);
 8712	}
 8713
 8714	for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++)
 8715		mlxsw_sp_mr_rif_del(vr->mr_table[i], rif);
 8716	ops->deconfigure(rif);
 8717	if (fid)
 8718		/* Loopback RIFs are not associated with a FID. */
 8719		mlxsw_sp_fid_put(fid);
 8720	mlxsw_sp->router->rifs[rif->rif_index] = NULL;
 8721	netdev_put(dev, &rif->dev_tracker);
 8722	mlxsw_sp_rif_free(rif);
 8723	mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
 8724	vr->rif_count--;
 8725	mlxsw_sp_vr_put(mlxsw_sp, vr);
 8726
 8727	if (crif->can_destroy)
 8728		mlxsw_sp_crif_free(crif);
 8729}
 8730
 8731void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
 8732				 struct net_device *dev)
 8733{
 8734	struct mlxsw_sp_rif *rif;
 8735
 8736	mutex_lock(&mlxsw_sp->router->lock);
 8737	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
 8738	if (!rif)
 8739		goto out;
 8740	mlxsw_sp_rif_destroy(rif);
 8741out:
 8742	mutex_unlock(&mlxsw_sp->router->lock);
 8743}
 8744
 8745static void mlxsw_sp_rif_destroy_vlan_upper(struct mlxsw_sp *mlxsw_sp,
 8746					    struct net_device *br_dev,
 8747					    u16 vid)
 8748{
 8749	struct net_device *upper_dev;
 8750	struct mlxsw_sp_crif *crif;
 8751
 8752	rcu_read_lock();
 8753	upper_dev = __vlan_find_dev_deep_rcu(br_dev, htons(ETH_P_8021Q), vid);
 8754	rcu_read_unlock();
 8755
 8756	if (!upper_dev)
 8757		return;
 8758
 8759	crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, upper_dev);
 8760	if (!crif || !crif->rif)
 8761		return;
 8762
 8763	mlxsw_sp_rif_destroy(crif->rif);
 8764}
 8765
 8766static int mlxsw_sp_inetaddr_bridge_event(struct mlxsw_sp *mlxsw_sp,
 8767					  struct net_device *l3_dev,
 8768					  int lower_pvid,
 8769					  unsigned long event,
 8770					  struct netlink_ext_ack *extack);
 8771
 8772int mlxsw_sp_router_bridge_vlan_add(struct mlxsw_sp *mlxsw_sp,
 8773				    struct net_device *br_dev,
 8774				    u16 new_vid, bool is_pvid,
 8775				    struct netlink_ext_ack *extack)
 8776{
 8777	struct mlxsw_sp_rif *old_rif;
 8778	struct mlxsw_sp_rif *new_rif;
 8779	struct net_device *upper_dev;
 8780	u16 old_pvid = 0;
 8781	u16 new_pvid;
 8782	int err = 0;
 8783
 8784	mutex_lock(&mlxsw_sp->router->lock);
 8785	old_rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, br_dev);
 8786	if (old_rif) {
 8787		/* If the RIF on the bridge is not a VLAN RIF, we shouldn't have
 8788		 * gotten a PVID notification.
 8789		 */
 8790		if (WARN_ON(old_rif->ops->type != MLXSW_SP_RIF_TYPE_VLAN))
 8791			old_rif = NULL;
 8792		else
 8793			old_pvid = mlxsw_sp_fid_8021q_vid(old_rif->fid);
 8794	}
 8795
 8796	if (is_pvid)
 8797		new_pvid = new_vid;
 8798	else if (old_pvid == new_vid)
 8799		new_pvid = 0;
 8800	else
 8801		goto out;
 8802
 8803	if (old_pvid == new_pvid)
 8804		goto out;
 8805
 8806	if (new_pvid) {
 8807		struct mlxsw_sp_rif_params params = {
 8808			.dev = br_dev,
 8809			.vid = new_pvid,
 8810		};
 8811
 8812		/* If there is a VLAN upper with the same VID as the new PVID,
 8813		 * kill its RIF, if there is one.
 8814		 */
 8815		mlxsw_sp_rif_destroy_vlan_upper(mlxsw_sp, br_dev, new_pvid);
 8816
 8817		if (mlxsw_sp_dev_addr_list_empty(br_dev))
 8818			goto out;
 8819		new_rif = mlxsw_sp_rif_create(mlxsw_sp, &params, extack);
 8820		if (IS_ERR(new_rif)) {
 8821			err = PTR_ERR(new_rif);
 8822			goto out;
 8823		}
 8824
 8825		if (old_pvid)
 8826			mlxsw_sp_rif_migrate_destroy(mlxsw_sp, old_rif, new_rif,
 8827						     true);
 8828	} else {
 8829		mlxsw_sp_rif_destroy(old_rif);
 8830	}
 8831
 8832	if (old_pvid) {
 8833		rcu_read_lock();
 8834		upper_dev = __vlan_find_dev_deep_rcu(br_dev, htons(ETH_P_8021Q),
 8835						     old_pvid);
 8836		rcu_read_unlock();
 8837		if (upper_dev)
 8838			err = mlxsw_sp_inetaddr_bridge_event(mlxsw_sp,
 8839							     upper_dev,
 8840							     new_pvid,
 8841							     NETDEV_UP, extack);
 8842	}
 8843
 8844out:
 8845	mutex_unlock(&mlxsw_sp->router->lock);
 8846	return err;
 8847}
 8848
 8849static void
 8850mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params *params,
 8851				 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
 8852{
 8853	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
 8854
 8855	params->vid = mlxsw_sp_port_vlan->vid;
 8856	params->lag = mlxsw_sp_port->lagged;
 8857	if (params->lag)
 8858		params->lag_id = mlxsw_sp_port->lag_id;
 8859	else
 8860		params->system_port = mlxsw_sp_port->local_port;
 8861}
 8862
 8863static struct mlxsw_sp_rif_subport *
 8864mlxsw_sp_rif_subport_rif(const struct mlxsw_sp_rif *rif)
 8865{
 8866	return container_of(rif, struct mlxsw_sp_rif_subport, common);
 8867}
 8868
 8869int mlxsw_sp_rif_subport_port(const struct mlxsw_sp_rif *rif,
 8870			      u16 *port, bool *is_lag)
 8871{
 8872	struct mlxsw_sp_rif_subport *rif_subport;
 8873
 8874	if (WARN_ON(rif->ops->type != MLXSW_SP_RIF_TYPE_SUBPORT))
 8875		return -EINVAL;
 8876
 8877	rif_subport = mlxsw_sp_rif_subport_rif(rif);
 8878	*is_lag = rif_subport->lag;
 8879	*port = *is_lag ? rif_subport->lag_id : rif_subport->system_port;
 8880	return 0;
 8881}
 8882
 8883static struct mlxsw_sp_rif *
 8884mlxsw_sp_rif_subport_get(struct mlxsw_sp *mlxsw_sp,
 8885			 const struct mlxsw_sp_rif_params *params,
 8886			 struct netlink_ext_ack *extack)
 8887{
 8888	struct mlxsw_sp_rif_subport *rif_subport;
 8889	struct mlxsw_sp_rif *rif;
 8890
 8891	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, params->dev);
 8892	if (!rif)
 8893		return mlxsw_sp_rif_create(mlxsw_sp, params, extack);
 8894
 8895	rif_subport = mlxsw_sp_rif_subport_rif(rif);
 8896	refcount_inc(&rif_subport->ref_count);
 8897	return rif;
 8898}
 8899
 8900static void mlxsw_sp_rif_subport_put(struct mlxsw_sp_rif *rif)
 8901{
 8902	struct mlxsw_sp_rif_subport *rif_subport;
 8903
 8904	rif_subport = mlxsw_sp_rif_subport_rif(rif);
 8905	if (!refcount_dec_and_test(&rif_subport->ref_count))
 8906		return;
 8907
 8908	mlxsw_sp_rif_destroy(rif);
 8909}
 8910
 8911static int mlxsw_sp_rif_mac_profile_index_alloc(struct mlxsw_sp *mlxsw_sp,
 8912						struct mlxsw_sp_rif_mac_profile *profile,
 8913						struct netlink_ext_ack *extack)
 8914{
 8915	u8 max_rif_mac_profiles = mlxsw_sp->router->max_rif_mac_profile;
 8916	struct mlxsw_sp_router *router = mlxsw_sp->router;
 8917	int id;
 8918
 8919	id = idr_alloc(&router->rif_mac_profiles_idr, profile, 0,
 8920		       max_rif_mac_profiles, GFP_KERNEL);
 8921
 8922	if (id >= 0) {
 8923		profile->id = id;
 8924		return 0;
 8925	}
 8926
 8927	if (id == -ENOSPC)
 8928		NL_SET_ERR_MSG_MOD(extack,
 8929				   "Exceeded number of supported router interface MAC profiles");
 8930
 8931	return id;
 8932}
 8933
 8934static struct mlxsw_sp_rif_mac_profile *
 8935mlxsw_sp_rif_mac_profile_index_free(struct mlxsw_sp *mlxsw_sp, u8 mac_profile)
 8936{
 8937	struct mlxsw_sp_rif_mac_profile *profile;
 8938
 8939	profile = idr_remove(&mlxsw_sp->router->rif_mac_profiles_idr,
 8940			     mac_profile);
 8941	WARN_ON(!profile);
 8942	return profile;
 8943}
 8944
 8945static struct mlxsw_sp_rif_mac_profile *
 8946mlxsw_sp_rif_mac_profile_alloc(const char *mac)
 8947{
 8948	struct mlxsw_sp_rif_mac_profile *profile;
 8949
 8950	profile = kzalloc(sizeof(*profile), GFP_KERNEL);
 8951	if (!profile)
 8952		return NULL;
 8953
 8954	ether_addr_copy(profile->mac_prefix, mac);
 8955	refcount_set(&profile->ref_count, 1);
 8956	return profile;
 8957}
 8958
 8959static struct mlxsw_sp_rif_mac_profile *
 8960mlxsw_sp_rif_mac_profile_find(const struct mlxsw_sp *mlxsw_sp, const char *mac)
 8961{
 8962	struct mlxsw_sp_router *router = mlxsw_sp->router;
 8963	struct mlxsw_sp_rif_mac_profile *profile;
 8964	int id;
 8965
 8966	idr_for_each_entry(&router->rif_mac_profiles_idr, profile, id) {
 8967		if (ether_addr_equal_masked(profile->mac_prefix, mac,
 8968					    mlxsw_sp->mac_mask))
 8969			return profile;
 8970	}
 8971
 8972	return NULL;
 8973}
 8974
 8975static u64 mlxsw_sp_rif_mac_profiles_occ_get(void *priv)
 8976{
 8977	const struct mlxsw_sp *mlxsw_sp = priv;
 8978
 8979	return atomic_read(&mlxsw_sp->router->rif_mac_profiles_count);
 8980}
 8981
 8982static u64 mlxsw_sp_rifs_occ_get(void *priv)
 8983{
 8984	const struct mlxsw_sp *mlxsw_sp = priv;
 8985
 8986	return atomic_read(&mlxsw_sp->router->rifs_count);
 8987}
 8988
 8989static struct mlxsw_sp_rif_mac_profile *
 8990mlxsw_sp_rif_mac_profile_create(struct mlxsw_sp *mlxsw_sp, const char *mac,
 8991				struct netlink_ext_ack *extack)
 8992{
 8993	struct mlxsw_sp_rif_mac_profile *profile;
 8994	int err;
 8995
 8996	profile = mlxsw_sp_rif_mac_profile_alloc(mac);
 8997	if (!profile)
 8998		return ERR_PTR(-ENOMEM);
 8999
 9000	err = mlxsw_sp_rif_mac_profile_index_alloc(mlxsw_sp, profile, extack);
 9001	if (err)
 9002		goto profile_index_alloc_err;
 9003
 9004	atomic_inc(&mlxsw_sp->router->rif_mac_profiles_count);
 9005	return profile;
 9006
 9007profile_index_alloc_err:
 9008	kfree(profile);
 9009	return ERR_PTR(err);
 9010}
 9011
 9012static void mlxsw_sp_rif_mac_profile_destroy(struct mlxsw_sp *mlxsw_sp,
 9013					     u8 mac_profile)
 9014{
 9015	struct mlxsw_sp_rif_mac_profile *profile;
 9016
 9017	atomic_dec(&mlxsw_sp->router->rif_mac_profiles_count);
 9018	profile = mlxsw_sp_rif_mac_profile_index_free(mlxsw_sp, mac_profile);
 9019	kfree(profile);
 9020}
 9021
 9022static int mlxsw_sp_rif_mac_profile_get(struct mlxsw_sp *mlxsw_sp,
 9023					const char *mac, u8 *p_mac_profile,
 9024					struct netlink_ext_ack *extack)
 9025{
 9026	struct mlxsw_sp_rif_mac_profile *profile;
 9027
 9028	profile = mlxsw_sp_rif_mac_profile_find(mlxsw_sp, mac);
 9029	if (profile) {
 9030		refcount_inc(&profile->ref_count);
 9031		goto out;
 9032	}
 9033
 9034	profile = mlxsw_sp_rif_mac_profile_create(mlxsw_sp, mac, extack);
 9035	if (IS_ERR(profile))
 9036		return PTR_ERR(profile);
 9037
 9038out:
 9039	*p_mac_profile = profile->id;
 9040	return 0;
 9041}
 9042
 9043static void mlxsw_sp_rif_mac_profile_put(struct mlxsw_sp *mlxsw_sp,
 9044					 u8 mac_profile)
 9045{
 9046	struct mlxsw_sp_rif_mac_profile *profile;
 9047
 9048	profile = idr_find(&mlxsw_sp->router->rif_mac_profiles_idr,
 9049			   mac_profile);
 9050	if (WARN_ON(!profile))
 9051		return;
 9052
 9053	if (!refcount_dec_and_test(&profile->ref_count))
 9054		return;
 9055
 9056	mlxsw_sp_rif_mac_profile_destroy(mlxsw_sp, mac_profile);
 9057}
 9058
 9059static bool mlxsw_sp_rif_mac_profile_is_shared(const struct mlxsw_sp_rif *rif)
 9060{
 9061	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
 9062	struct mlxsw_sp_rif_mac_profile *profile;
 9063
 9064	profile = idr_find(&mlxsw_sp->router->rif_mac_profiles_idr,
 9065			   rif->mac_profile_id);
 9066	if (WARN_ON(!profile))
 9067		return false;
 9068
 9069	return refcount_read(&profile->ref_count) > 1;
 9070}
 9071
 9072static int mlxsw_sp_rif_mac_profile_edit(struct mlxsw_sp_rif *rif,
 9073					 const char *new_mac)
 9074{
 9075	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
 9076	struct mlxsw_sp_rif_mac_profile *profile;
 9077
 9078	profile = idr_find(&mlxsw_sp->router->rif_mac_profiles_idr,
 9079			   rif->mac_profile_id);
 9080	if (WARN_ON(!profile))
 9081		return -EINVAL;
 9082
 9083	ether_addr_copy(profile->mac_prefix, new_mac);
 9084	return 0;
 9085}
 9086
 9087static int
 9088mlxsw_sp_rif_mac_profile_replace(struct mlxsw_sp *mlxsw_sp,
 9089				 struct mlxsw_sp_rif *rif,
 9090				 const char *new_mac,
 9091				 struct netlink_ext_ack *extack)
 9092{
 9093	u8 mac_profile;
 9094	int err;
 9095
 9096	if (!mlxsw_sp_rif_mac_profile_is_shared(rif) &&
 9097	    !mlxsw_sp_rif_mac_profile_find(mlxsw_sp, new_mac))
 9098		return mlxsw_sp_rif_mac_profile_edit(rif, new_mac);
 9099
 9100	err = mlxsw_sp_rif_mac_profile_get(mlxsw_sp, new_mac,
 9101					   &mac_profile, extack);
 9102	if (err)
 9103		return err;
 9104
 9105	mlxsw_sp_rif_mac_profile_put(mlxsw_sp, rif->mac_profile_id);
 9106	rif->mac_profile_id = mac_profile;
 9107	return 0;
 9108}
 9109
 9110static int
 9111__mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
 9112				 struct net_device *l3_dev,
 9113				 struct netlink_ext_ack *extack)
 9114{
 9115	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
 9116	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
 9117	struct mlxsw_sp_rif_params params;
 9118	u16 vid = mlxsw_sp_port_vlan->vid;
 9119	struct mlxsw_sp_rif *rif;
 9120	struct mlxsw_sp_fid *fid;
 9121	int err;
 9122
 9123	params = (struct mlxsw_sp_rif_params) {
 9124		.dev = l3_dev,
 9125		.vid = vid,
 9126	};
 9127
 9128	mlxsw_sp_rif_subport_params_init(&params, mlxsw_sp_port_vlan);
 9129	rif = mlxsw_sp_rif_subport_get(mlxsw_sp, &params, extack);
 9130	if (IS_ERR(rif))
 9131		return PTR_ERR(rif);
 9132
 9133	/* FID was already created, just take a reference */
 9134	fid = rif->ops->fid_get(rif, &params, extack);
 9135	err = mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port, vid);
 9136	if (err)
 9137		goto err_fid_port_vid_map;
 9138
 9139	err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, false);
 9140	if (err)
 9141		goto err_port_vid_learning_set;
 9142
 9143	err = mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid,
 9144					BR_STATE_FORWARDING);
 9145	if (err)
 9146		goto err_port_vid_stp_set;
 9147
 9148	mlxsw_sp_port_vlan->fid = fid;
 9149
 9150	return 0;
 9151
 9152err_port_vid_stp_set:
 9153	mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
 9154err_port_vid_learning_set:
 9155	mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid);
 9156err_fid_port_vid_map:
 9157	mlxsw_sp_fid_put(fid);
 9158	mlxsw_sp_rif_subport_put(rif);
 9159	return err;
 9160}
 9161
 9162static void
 9163__mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
 9164{
 9165	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
 9166	struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
 9167	struct mlxsw_sp_rif *rif = mlxsw_sp_fid_rif(fid);
 9168	u16 vid = mlxsw_sp_port_vlan->vid;
 9169
 9170	if (WARN_ON(mlxsw_sp_fid_type(fid) != MLXSW_SP_FID_TYPE_RFID))
 9171		return;
 9172
 9173	mlxsw_sp_port_vlan->fid = NULL;
 9174	mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid, BR_STATE_BLOCKING);
 9175	mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
 9176	mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid);
 9177	mlxsw_sp_fid_put(fid);
 9178	mlxsw_sp_rif_subport_put(rif);
 9179}
 9180
 9181static int
 9182mlxsw_sp_port_vlan_router_join_existing(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
 9183					struct net_device *l3_dev,
 9184					struct netlink_ext_ack *extack)
 9185{
 9186	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port_vlan->mlxsw_sp_port->mlxsw_sp;
 9187
 9188	lockdep_assert_held(&mlxsw_sp->router->lock);
 9189
 9190	if (!mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev))
 9191		return 0;
 9192
 9193	return __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, l3_dev,
 9194						extack);
 9195}
 9196
 9197void
 9198mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
 9199{
 9200	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port_vlan->mlxsw_sp_port->mlxsw_sp;
 9201
 9202	mutex_lock(&mlxsw_sp->router->lock);
 9203	__mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
 9204	mutex_unlock(&mlxsw_sp->router->lock);
 9205}
 9206
 9207static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev,
 9208					     struct net_device *port_dev,
 9209					     unsigned long event, u16 vid,
 9210					     struct netlink_ext_ack *extack)
 9211{
 9212	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(port_dev);
 9213	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
 9214
 9215	mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
 9216	if (WARN_ON(!mlxsw_sp_port_vlan))
 9217		return -EINVAL;
 9218
 9219	switch (event) {
 9220	case NETDEV_UP:
 9221		return __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan,
 9222							l3_dev, extack);
 9223	case NETDEV_DOWN:
 9224		__mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
 9225		break;
 9226	}
 9227
 9228	return 0;
 9229}
 9230
 9231static int mlxsw_sp_inetaddr_port_event(struct net_device *port_dev,
 9232					unsigned long event, bool nomaster,
 9233					struct netlink_ext_ack *extack)
 9234{
 9235	if (!nomaster && (netif_is_any_bridge_port(port_dev) ||
 9236			  netif_is_lag_port(port_dev)))
 9237		return 0;
 9238
 9239	return mlxsw_sp_inetaddr_port_vlan_event(port_dev, port_dev, event,
 9240						 MLXSW_SP_DEFAULT_VID, extack);
 9241}
 9242
 9243static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev,
 9244					 struct net_device *lag_dev,
 9245					 unsigned long event, u16 vid,
 9246					 struct netlink_ext_ack *extack)
 9247{
 9248	struct net_device *port_dev;
 9249	struct list_head *iter;
 9250	int err;
 9251
 9252	netdev_for_each_lower_dev(lag_dev, port_dev, iter) {
 9253		if (mlxsw_sp_port_dev_check(port_dev)) {
 9254			err = mlxsw_sp_inetaddr_port_vlan_event(l3_dev,
 9255								port_dev,
 9256								event, vid,
 9257								extack);
 9258			if (err)
 9259				return err;
 9260		}
 9261	}
 9262
 9263	return 0;
 9264}
 9265
 9266static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev,
 9267				       unsigned long event, bool nomaster,
 9268				       struct netlink_ext_ack *extack)
 9269{
 9270	if (!nomaster && netif_is_bridge_port(lag_dev))
 9271		return 0;
 9272
 9273	return __mlxsw_sp_inetaddr_lag_event(lag_dev, lag_dev, event,
 9274					     MLXSW_SP_DEFAULT_VID, extack);
 9275}
 9276
 9277static int mlxsw_sp_inetaddr_bridge_event(struct mlxsw_sp *mlxsw_sp,
 9278					  struct net_device *l3_dev,
 9279					  int lower_pvid,
 9280					  unsigned long event,
 9281					  struct netlink_ext_ack *extack)
 9282{
 9283	struct mlxsw_sp_rif_params params = {
 9284		.dev = l3_dev,
 9285	};
 9286	struct mlxsw_sp_rif *rif;
 9287	int err;
 9288
 9289	switch (event) {
 9290	case NETDEV_UP:
 9291		if (netif_is_bridge_master(l3_dev) && br_vlan_enabled(l3_dev)) {
 9292			u16 proto;
 9293
 9294			br_vlan_get_proto(l3_dev, &proto);
 9295			if (proto == ETH_P_8021AD) {
 9296				NL_SET_ERR_MSG_MOD(extack, "Adding an IP address to 802.1ad bridge is not supported");
 9297				return -EOPNOTSUPP;
 9298			}
 9299			err = br_vlan_get_pvid(l3_dev, &params.vid);
 9300			if (err)
 9301				return err;
 9302			if (!params.vid)
 9303				return 0;
 9304		} else if (is_vlan_dev(l3_dev)) {
 9305			params.vid = vlan_dev_vlan_id(l3_dev);
 9306
 9307			/* If the VID matches PVID of the bridge below, the
 9308			 * bridge owns the RIF for this VLAN. Don't do anything.
 9309			 */
 9310			if ((int)params.vid == lower_pvid)
 9311				return 0;
 9312		}
 9313
 9314		rif = mlxsw_sp_rif_create(mlxsw_sp, &params, extack);
 9315		if (IS_ERR(rif))
 9316			return PTR_ERR(rif);
 9317		break;
 9318	case NETDEV_DOWN:
 9319		rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
 9320		mlxsw_sp_rif_destroy(rif);
 9321		break;
 9322	}
 9323
 9324	return 0;
 9325}
 9326
 9327static int mlxsw_sp_inetaddr_vlan_event(struct mlxsw_sp *mlxsw_sp,
 9328					struct net_device *vlan_dev,
 9329					unsigned long event, bool nomaster,
 9330					struct netlink_ext_ack *extack)
 9331{
 9332	struct net_device *real_dev = vlan_dev_real_dev(vlan_dev);
 9333	u16 vid = vlan_dev_vlan_id(vlan_dev);
 9334	u16 lower_pvid;
 9335	int err;
 9336
 9337	if (!nomaster && netif_is_bridge_port(vlan_dev))
 9338		return 0;
 9339
 9340	if (mlxsw_sp_port_dev_check(real_dev)) {
 9341		return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev, real_dev,
 9342							 event, vid, extack);
 9343	} else if (netif_is_lag_master(real_dev)) {
 9344		return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event,
 9345						     vid, extack);
 9346	} else if (netif_is_bridge_master(real_dev) &&
 9347		   br_vlan_enabled(real_dev)) {
 9348		err = br_vlan_get_pvid(real_dev, &lower_pvid);
 9349		if (err)
 9350			return err;
 9351		return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp, vlan_dev,
 9352						      lower_pvid, event,
 9353						      extack);
 9354	}
 9355
 9356	return 0;
 9357}
 9358
 9359static bool mlxsw_sp_rif_macvlan_is_vrrp4(const u8 *mac)
 9360{
 9361	u8 vrrp4[ETH_ALEN] = { 0x00, 0x00, 0x5e, 0x00, 0x01, 0x00 };
 9362	u8 mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
 9363
 9364	return ether_addr_equal_masked(mac, vrrp4, mask);
 9365}
 9366
 9367static bool mlxsw_sp_rif_macvlan_is_vrrp6(const u8 *mac)
 9368{
 9369	u8 vrrp6[ETH_ALEN] = { 0x00, 0x00, 0x5e, 0x00, 0x02, 0x00 };
 9370	u8 mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
 9371
 9372	return ether_addr_equal_masked(mac, vrrp6, mask);
 9373}
 9374
 9375static int mlxsw_sp_rif_vrrp_op(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
 9376				const u8 *mac, bool adding)
 9377{
 9378	char ritr_pl[MLXSW_REG_RITR_LEN];
 9379	u8 vrrp_id = adding ? mac[5] : 0;
 9380	int err;
 9381
 9382	if (!mlxsw_sp_rif_macvlan_is_vrrp4(mac) &&
 9383	    !mlxsw_sp_rif_macvlan_is_vrrp6(mac))
 9384		return 0;
 9385
 9386	mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
 9387	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
 9388	if (err)
 9389		return err;
 9390
 9391	if (mlxsw_sp_rif_macvlan_is_vrrp4(mac))
 9392		mlxsw_reg_ritr_if_vrrp_id_ipv4_set(ritr_pl, vrrp_id);
 9393	else
 9394		mlxsw_reg_ritr_if_vrrp_id_ipv6_set(ritr_pl, vrrp_id);
 9395
 9396	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
 9397}
 9398
 9399static int mlxsw_sp_rif_macvlan_add(struct mlxsw_sp *mlxsw_sp,
 9400				    const struct net_device *macvlan_dev,
 9401				    struct netlink_ext_ack *extack)
 9402{
 9403	struct macvlan_dev *vlan = netdev_priv(macvlan_dev);
 9404	struct mlxsw_sp_rif *rif;
 9405	int err;
 9406
 9407	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, vlan->lowerdev);
 9408	if (!rif)
 9409		return 0;
 9410
 9411	err = mlxsw_sp_rif_fdb_op(mlxsw_sp, macvlan_dev->dev_addr,
 9412				  mlxsw_sp_fid_index(rif->fid), true);
 9413	if (err)
 9414		return err;
 9415
 9416	err = mlxsw_sp_rif_vrrp_op(mlxsw_sp, rif->rif_index,
 9417				   macvlan_dev->dev_addr, true);
 9418	if (err)
 9419		goto err_rif_vrrp_add;
 9420
 9421	/* Make sure the bridge driver does not have this MAC pointing at
 9422	 * some other port.
 9423	 */
 9424	if (rif->ops->fdb_del)
 9425		rif->ops->fdb_del(rif, macvlan_dev->dev_addr);
 9426
 9427	return 0;
 9428
 9429err_rif_vrrp_add:
 9430	mlxsw_sp_rif_fdb_op(mlxsw_sp, macvlan_dev->dev_addr,
 9431			    mlxsw_sp_fid_index(rif->fid), false);
 9432	return err;
 9433}
 9434
 9435static void __mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
 9436				       const struct net_device *macvlan_dev)
 9437{
 9438	struct macvlan_dev *vlan = netdev_priv(macvlan_dev);
 9439	struct mlxsw_sp_rif *rif;
 9440
 9441	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, vlan->lowerdev);
 9442	/* If we do not have a RIF, then we already took care of
 9443	 * removing the macvlan's MAC during RIF deletion.
 9444	 */
 9445	if (!rif)
 9446		return;
 9447	mlxsw_sp_rif_vrrp_op(mlxsw_sp, rif->rif_index, macvlan_dev->dev_addr,
 9448			     false);
 9449	mlxsw_sp_rif_fdb_op(mlxsw_sp, macvlan_dev->dev_addr,
 9450			    mlxsw_sp_fid_index(rif->fid), false);
 9451}
 9452
 9453void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
 9454			      const struct net_device *macvlan_dev)
 9455{
 9456	mutex_lock(&mlxsw_sp->router->lock);
 9457	__mlxsw_sp_rif_macvlan_del(mlxsw_sp, macvlan_dev);
 9458	mutex_unlock(&mlxsw_sp->router->lock);
 9459}
 9460
 9461static int mlxsw_sp_inetaddr_macvlan_event(struct mlxsw_sp *mlxsw_sp,
 9462					   struct net_device *macvlan_dev,
 9463					   unsigned long event,
 9464					   struct netlink_ext_ack *extack)
 9465{
 9466	switch (event) {
 9467	case NETDEV_UP:
 9468		return mlxsw_sp_rif_macvlan_add(mlxsw_sp, macvlan_dev, extack);
 9469	case NETDEV_DOWN:
 9470		__mlxsw_sp_rif_macvlan_del(mlxsw_sp, macvlan_dev);
 9471		break;
 9472	}
 9473
 9474	return 0;
 9475}
 9476
 9477static int __mlxsw_sp_inetaddr_event(struct mlxsw_sp *mlxsw_sp,
 9478				     struct net_device *dev,
 9479				     unsigned long event, bool nomaster,
 9480				     struct netlink_ext_ack *extack)
 9481{
 9482	if (mlxsw_sp_port_dev_check(dev))
 9483		return mlxsw_sp_inetaddr_port_event(dev, event, nomaster,
 9484						    extack);
 9485	else if (netif_is_lag_master(dev))
 9486		return mlxsw_sp_inetaddr_lag_event(dev, event, nomaster,
 9487						   extack);
 9488	else if (netif_is_bridge_master(dev))
 9489		return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp, dev, -1, event,
 9490						      extack);
 9491	else if (is_vlan_dev(dev))
 9492		return mlxsw_sp_inetaddr_vlan_event(mlxsw_sp, dev, event,
 9493						    nomaster, extack);
 9494	else if (netif_is_macvlan(dev))
 9495		return mlxsw_sp_inetaddr_macvlan_event(mlxsw_sp, dev, event,
 9496						       extack);
 9497	else
 9498		return 0;
 9499}
 9500
 9501static int mlxsw_sp_inetaddr_event(struct notifier_block *nb,
 9502				   unsigned long event, void *ptr)
 9503{
 9504	struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
 9505	struct net_device *dev = ifa->ifa_dev->dev;
 9506	struct mlxsw_sp_router *router;
 9507	struct mlxsw_sp_rif *rif;
 9508	int err = 0;
 9509
 9510	/* NETDEV_UP event is handled by mlxsw_sp_inetaddr_valid_event */
 9511	if (event == NETDEV_UP)
 9512		return NOTIFY_DONE;
 9513
 9514	router = container_of(nb, struct mlxsw_sp_router, inetaddr_nb);
 9515	mutex_lock(&router->lock);
 9516	rif = mlxsw_sp_rif_find_by_dev(router->mlxsw_sp, dev);
 9517	if (!mlxsw_sp_rif_should_config(rif, dev, event))
 9518		goto out;
 9519
 9520	err = __mlxsw_sp_inetaddr_event(router->mlxsw_sp, dev, event, false,
 9521					NULL);
 9522out:
 9523	mutex_unlock(&router->lock);
 9524	return notifier_from_errno(err);
 9525}
 9526
 9527static int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
 9528					 unsigned long event, void *ptr)
 9529{
 9530	struct in_validator_info *ivi = (struct in_validator_info *) ptr;
 9531	struct net_device *dev = ivi->ivi_dev->dev;
 9532	struct mlxsw_sp *mlxsw_sp;
 9533	struct mlxsw_sp_rif *rif;
 9534	int err = 0;
 9535
 9536	mlxsw_sp = mlxsw_sp_lower_get(dev);
 9537	if (!mlxsw_sp)
 9538		return NOTIFY_DONE;
 9539
 9540	mutex_lock(&mlxsw_sp->router->lock);
 9541	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
 9542	if (!mlxsw_sp_rif_should_config(rif, dev, event))
 9543		goto out;
 9544
 9545	err = __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, false,
 9546					ivi->extack);
 9547out:
 9548	mutex_unlock(&mlxsw_sp->router->lock);
 9549	return notifier_from_errno(err);
 9550}
 9551
 9552struct mlxsw_sp_inet6addr_event_work {
 9553	struct work_struct work;
 9554	struct mlxsw_sp *mlxsw_sp;
 9555	struct net_device *dev;
 9556	netdevice_tracker dev_tracker;
 9557	unsigned long event;
 9558};
 9559
 9560static void mlxsw_sp_inet6addr_event_work(struct work_struct *work)
 9561{
 9562	struct mlxsw_sp_inet6addr_event_work *inet6addr_work =
 9563		container_of(work, struct mlxsw_sp_inet6addr_event_work, work);
 9564	struct mlxsw_sp *mlxsw_sp = inet6addr_work->mlxsw_sp;
 9565	struct net_device *dev = inet6addr_work->dev;
 9566	unsigned long event = inet6addr_work->event;
 9567	struct mlxsw_sp_rif *rif;
 9568
 9569	rtnl_lock();
 9570	mutex_lock(&mlxsw_sp->router->lock);
 9571
 9572	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
 9573	if (!mlxsw_sp_rif_should_config(rif, dev, event))
 9574		goto out;
 9575
 9576	__mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, false, NULL);
 9577out:
 9578	mutex_unlock(&mlxsw_sp->router->lock);
 9579	rtnl_unlock();
 9580	netdev_put(dev, &inet6addr_work->dev_tracker);
 9581	kfree(inet6addr_work);
 9582}
 9583
 9584/* Called with rcu_read_lock() */
 9585static int mlxsw_sp_inet6addr_event(struct notifier_block *nb,
 9586				    unsigned long event, void *ptr)
 9587{
 9588	struct inet6_ifaddr *if6 = (struct inet6_ifaddr *) ptr;
 9589	struct mlxsw_sp_inet6addr_event_work *inet6addr_work;
 9590	struct net_device *dev = if6->idev->dev;
 9591	struct mlxsw_sp_router *router;
 9592
 9593	/* NETDEV_UP event is handled by mlxsw_sp_inet6addr_valid_event */
 9594	if (event == NETDEV_UP)
 9595		return NOTIFY_DONE;
 9596
 9597	inet6addr_work = kzalloc(sizeof(*inet6addr_work), GFP_ATOMIC);
 9598	if (!inet6addr_work)
 9599		return NOTIFY_BAD;
 9600
 9601	router = container_of(nb, struct mlxsw_sp_router, inet6addr_nb);
 9602	INIT_WORK(&inet6addr_work->work, mlxsw_sp_inet6addr_event_work);
 9603	inet6addr_work->mlxsw_sp = router->mlxsw_sp;
 9604	inet6addr_work->dev = dev;
 9605	inet6addr_work->event = event;
 9606	netdev_hold(dev, &inet6addr_work->dev_tracker, GFP_ATOMIC);
 9607	mlxsw_core_schedule_work(&inet6addr_work->work);
 9608
 9609	return NOTIFY_DONE;
 9610}
 9611
 9612static int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
 9613					  unsigned long event, void *ptr)
 9614{
 9615	struct in6_validator_info *i6vi = (struct in6_validator_info *) ptr;
 9616	struct net_device *dev = i6vi->i6vi_dev->dev;
 9617	struct mlxsw_sp *mlxsw_sp;
 9618	struct mlxsw_sp_rif *rif;
 9619	int err = 0;
 9620
 9621	mlxsw_sp = mlxsw_sp_lower_get(dev);
 9622	if (!mlxsw_sp)
 9623		return NOTIFY_DONE;
 9624
 9625	mutex_lock(&mlxsw_sp->router->lock);
 9626	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
 9627	if (!mlxsw_sp_rif_should_config(rif, dev, event))
 9628		goto out;
 9629
 9630	err = __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, false,
 9631					i6vi->extack);
 9632out:
 9633	mutex_unlock(&mlxsw_sp->router->lock);
 9634	return notifier_from_errno(err);
 9635}
 9636
 9637static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
 9638			     const char *mac, int mtu, u8 mac_profile)
 9639{
 9640	char ritr_pl[MLXSW_REG_RITR_LEN];
 9641	int err;
 9642
 9643	mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
 9644	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
 9645	if (err)
 9646		return err;
 9647
 9648	mlxsw_reg_ritr_mtu_set(ritr_pl, mtu);
 9649	mlxsw_reg_ritr_if_mac_memcpy_to(ritr_pl, mac);
 9650	mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, mac_profile);
 9651	mlxsw_reg_ritr_op_set(ritr_pl, MLXSW_REG_RITR_RIF_CREATE);
 9652	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
 9653}
 9654
 9655static int
 9656mlxsw_sp_router_port_change_event(struct mlxsw_sp *mlxsw_sp,
 9657				  struct mlxsw_sp_rif *rif,
 9658				  struct netlink_ext_ack *extack)
 9659{
 9660	struct net_device *dev = mlxsw_sp_rif_dev(rif);
 9661	u8 old_mac_profile;
 9662	u16 fid_index;
 9663	int err;
 9664
 9665	fid_index = mlxsw_sp_fid_index(rif->fid);
 9666
 9667	err = mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, false);
 9668	if (err)
 9669		return err;
 9670
 9671	old_mac_profile = rif->mac_profile_id;
 9672	err = mlxsw_sp_rif_mac_profile_replace(mlxsw_sp, rif, dev->dev_addr,
 9673					       extack);
 9674	if (err)
 9675		goto err_rif_mac_profile_replace;
 9676
 9677	err = mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, dev->dev_addr,
 9678				dev->mtu, rif->mac_profile_id);
 9679	if (err)
 9680		goto err_rif_edit;
 9681
 9682	err = mlxsw_sp_rif_fdb_op(mlxsw_sp, dev->dev_addr, fid_index, true);
 9683	if (err)
 9684		goto err_rif_fdb_op;
 9685
 9686	if (rif->mtu != dev->mtu) {
 9687		struct mlxsw_sp_vr *vr;
 9688		int i;
 9689
 9690		/* The RIF is relevant only to its mr_table instance, as unlike
 9691		 * unicast routing, in multicast routing a RIF cannot be shared
 9692		 * between several multicast routing tables.
 9693		 */
 9694		vr = &mlxsw_sp->router->vrs[rif->vr_id];
 9695		for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++)
 9696			mlxsw_sp_mr_rif_mtu_update(vr->mr_table[i],
 9697						   rif, dev->mtu);
 9698	}
 9699
 9700	ether_addr_copy(rif->addr, dev->dev_addr);
 9701	rif->mtu = dev->mtu;
 9702
 9703	netdev_dbg(dev, "Updated RIF=%d\n", rif->rif_index);
 9704
 9705	return 0;
 9706
 9707err_rif_fdb_op:
 9708	mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, rif->addr, rif->mtu,
 9709			  old_mac_profile);
 9710err_rif_edit:
 9711	mlxsw_sp_rif_mac_profile_replace(mlxsw_sp, rif, rif->addr, extack);
 9712err_rif_mac_profile_replace:
 9713	mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, true);
 9714	return err;
 9715}
 9716
 9717static int mlxsw_sp_router_port_pre_changeaddr_event(struct mlxsw_sp_rif *rif,
 9718			    struct netdev_notifier_pre_changeaddr_info *info)
 9719{
 9720	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
 9721	struct mlxsw_sp_rif_mac_profile *profile;
 9722	struct netlink_ext_ack *extack;
 9723	u8 max_rif_mac_profiles;
 9724	u64 occ;
 9725
 9726	extack = netdev_notifier_info_to_extack(&info->info);
 9727
 9728	profile = mlxsw_sp_rif_mac_profile_find(mlxsw_sp, info->dev_addr);
 9729	if (profile)
 9730		return 0;
 9731
 9732	max_rif_mac_profiles = mlxsw_sp->router->max_rif_mac_profile;
 9733	occ = mlxsw_sp_rif_mac_profiles_occ_get(mlxsw_sp);
 9734	if (occ < max_rif_mac_profiles)
 9735		return 0;
 9736
 9737	if (!mlxsw_sp_rif_mac_profile_is_shared(rif))
 9738		return 0;
 9739
 9740	NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported router interface MAC profiles");
 9741	return -ENOBUFS;
 9742}
 9743
 9744static bool mlxsw_sp_router_netdevice_interesting(struct mlxsw_sp *mlxsw_sp,
 9745						  struct net_device *dev)
 9746{
 9747	struct vlan_dev_priv *vlan;
 9748
 9749	if (netif_is_lag_master(dev) ||
 9750	    netif_is_bridge_master(dev) ||
 9751	    mlxsw_sp_port_dev_check(dev) ||
 9752	    mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev) ||
 9753	    netif_is_l3_master(dev))
 9754		return true;
 9755
 9756	if (!is_vlan_dev(dev))
 9757		return false;
 9758
 9759	vlan = vlan_dev_priv(dev);
 9760	return netif_is_lag_master(vlan->real_dev) ||
 9761	       netif_is_bridge_master(vlan->real_dev) ||
 9762	       mlxsw_sp_port_dev_check(vlan->real_dev);
 9763}
 9764
 9765static struct mlxsw_sp_crif *
 9766mlxsw_sp_crif_register(struct mlxsw_sp_router *router, struct net_device *dev)
 9767{
 9768	struct mlxsw_sp_crif *crif;
 9769	int err;
 9770
 9771	if (WARN_ON(mlxsw_sp_crif_lookup(router, dev)))
 9772		return NULL;
 9773
 9774	crif = mlxsw_sp_crif_alloc(dev);
 9775	if (!crif)
 9776		return ERR_PTR(-ENOMEM);
 9777
 9778	err = mlxsw_sp_crif_insert(router, crif);
 9779	if (err)
 9780		goto err_netdev_insert;
 9781
 9782	return crif;
 9783
 9784err_netdev_insert:
 9785	mlxsw_sp_crif_free(crif);
 9786	return ERR_PTR(err);
 9787}
 9788
 9789static void mlxsw_sp_crif_unregister(struct mlxsw_sp_router *router,
 9790				     struct mlxsw_sp_crif *crif)
 9791{
 9792	struct mlxsw_sp_nexthop *nh, *tmp;
 9793
 9794	mlxsw_sp_crif_remove(router, crif);
 9795
 9796	list_for_each_entry_safe(nh, tmp, &crif->nexthop_list, crif_list_node)
 9797		mlxsw_sp_nexthop_type_fini(router->mlxsw_sp, nh);
 9798
 9799	if (crif->rif)
 9800		crif->can_destroy = true;
 9801	else
 9802		mlxsw_sp_crif_free(crif);
 9803}
 9804
 9805static int mlxsw_sp_netdevice_register(struct mlxsw_sp_router *router,
 9806				       struct net_device *dev)
 9807{
 9808	struct mlxsw_sp_crif *crif;
 9809
 9810	if (!mlxsw_sp_router_netdevice_interesting(router->mlxsw_sp, dev))
 9811		return 0;
 9812
 9813	crif = mlxsw_sp_crif_register(router, dev);
 9814	return PTR_ERR_OR_ZERO(crif);
 9815}
 9816
 9817static void mlxsw_sp_netdevice_unregister(struct mlxsw_sp_router *router,
 9818					  struct net_device *dev)
 9819{
 9820	struct mlxsw_sp_crif *crif;
 9821
 9822	if (!mlxsw_sp_router_netdevice_interesting(router->mlxsw_sp, dev))
 9823		return;
 9824
 9825	/* netdev_run_todo(), by way of netdev_wait_allrefs_any(), rebroadcasts
 9826	 * the NETDEV_UNREGISTER message, so we can get here twice. If that's
 9827	 * what happened, the netdevice state is NETREG_UNREGISTERED. In that
 9828	 * case, we expect to have collected the CRIF already, and warn if it
 9829	 * still exists. Otherwise we expect the CRIF to exist.
 9830	 */
 9831	crif = mlxsw_sp_crif_lookup(router, dev);
 9832	if (dev->reg_state == NETREG_UNREGISTERED) {
 9833		if (!WARN_ON(crif))
 9834			return;
 9835	}
 9836	if (WARN_ON(!crif))
 9837		return;
 9838
 9839	mlxsw_sp_crif_unregister(router, crif);
 9840}
 9841
 9842static bool mlxsw_sp_is_offload_xstats_event(unsigned long event)
 9843{
 9844	switch (event) {
 9845	case NETDEV_OFFLOAD_XSTATS_ENABLE:
 9846	case NETDEV_OFFLOAD_XSTATS_DISABLE:
 9847	case NETDEV_OFFLOAD_XSTATS_REPORT_USED:
 9848	case NETDEV_OFFLOAD_XSTATS_REPORT_DELTA:
 9849		return true;
 9850	}
 9851
 9852	return false;
 9853}
 9854
 9855static int
 9856mlxsw_sp_router_port_offload_xstats_cmd(struct mlxsw_sp_rif *rif,
 9857					unsigned long event,
 9858					struct netdev_notifier_offload_xstats_info *info)
 9859{
 9860	switch (info->type) {
 9861	case NETDEV_OFFLOAD_XSTATS_TYPE_L3:
 9862		break;
 9863	default:
 9864		return 0;
 9865	}
 9866
 9867	switch (event) {
 9868	case NETDEV_OFFLOAD_XSTATS_ENABLE:
 9869		return mlxsw_sp_router_port_l3_stats_enable(rif);
 9870	case NETDEV_OFFLOAD_XSTATS_DISABLE:
 9871		mlxsw_sp_router_port_l3_stats_disable(rif);
 9872		return 0;
 9873	case NETDEV_OFFLOAD_XSTATS_REPORT_USED:
 9874		mlxsw_sp_router_port_l3_stats_report_used(rif, info);
 9875		return 0;
 9876	case NETDEV_OFFLOAD_XSTATS_REPORT_DELTA:
 9877		return mlxsw_sp_router_port_l3_stats_report_delta(rif, info);
 9878	}
 9879
 9880	WARN_ON_ONCE(1);
 9881	return 0;
 9882}
 9883
 9884static int
 9885mlxsw_sp_netdevice_offload_xstats_cmd(struct mlxsw_sp *mlxsw_sp,
 9886				      struct net_device *dev,
 9887				      unsigned long event,
 9888				      struct netdev_notifier_offload_xstats_info *info)
 9889{
 9890	struct mlxsw_sp_rif *rif;
 9891
 9892	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
 9893	if (!rif)
 9894		return 0;
 9895
 9896	return mlxsw_sp_router_port_offload_xstats_cmd(rif, event, info);
 9897}
 9898
 9899static bool mlxsw_sp_is_router_event(unsigned long event)
 9900{
 9901	switch (event) {
 9902	case NETDEV_PRE_CHANGEADDR:
 9903	case NETDEV_CHANGEADDR:
 9904	case NETDEV_CHANGEMTU:
 9905		return true;
 9906	default:
 9907		return false;
 9908	}
 9909}
 9910
 9911static int mlxsw_sp_netdevice_router_port_event(struct net_device *dev,
 9912						unsigned long event, void *ptr)
 9913{
 9914	struct netlink_ext_ack *extack = netdev_notifier_info_to_extack(ptr);
 9915	struct mlxsw_sp *mlxsw_sp;
 9916	struct mlxsw_sp_rif *rif;
 9917
 9918	mlxsw_sp = mlxsw_sp_lower_get(dev);
 9919	if (!mlxsw_sp)
 9920		return 0;
 9921
 9922	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
 9923	if (!rif)
 9924		return 0;
 9925
 9926	switch (event) {
 9927	case NETDEV_CHANGEMTU:
 9928	case NETDEV_CHANGEADDR:
 9929		return mlxsw_sp_router_port_change_event(mlxsw_sp, rif, extack);
 9930	case NETDEV_PRE_CHANGEADDR:
 9931		return mlxsw_sp_router_port_pre_changeaddr_event(rif, ptr);
 9932	default:
 9933		WARN_ON_ONCE(1);
 9934		break;
 9935	}
 9936
 9937	return 0;
 9938}
 9939
 9940static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp,
 9941				  struct net_device *l3_dev,
 9942				  struct netlink_ext_ack *extack)
 9943{
 9944	struct mlxsw_sp_rif *rif;
 9945
 9946	/* If netdev is already associated with a RIF, then we need to
 9947	 * destroy it and create a new one with the new virtual router ID.
 9948	 */
 9949	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
 9950	if (rif)
 9951		__mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_DOWN, false,
 9952					  extack);
 9953
 9954	return __mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_UP, false,
 9955					 extack);
 9956}
 9957
 9958static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp,
 9959				    struct net_device *l3_dev)
 9960{
 9961	struct mlxsw_sp_rif *rif;
 9962
 9963	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
 9964	if (!rif)
 9965		return;
 9966	__mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_DOWN, false, NULL);
 9967}
 9968
 9969static bool mlxsw_sp_is_vrf_event(unsigned long event, void *ptr)
 9970{
 9971	struct netdev_notifier_changeupper_info *info = ptr;
 9972
 9973	if (event != NETDEV_PRECHANGEUPPER && event != NETDEV_CHANGEUPPER)
 9974		return false;
 9975	return netif_is_l3_master(info->upper_dev);
 9976}
 9977
 9978static int
 9979mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
 9980			     struct netdev_notifier_changeupper_info *info)
 9981{
 9982	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
 9983	int err = 0;
 9984
 9985	/* We do not create a RIF for a macvlan, but only use it to
 9986	 * direct more MAC addresses to the router.
 9987	 */
 9988	if (!mlxsw_sp || netif_is_macvlan(l3_dev))
 9989		return 0;
 9990
 9991	switch (event) {
 9992	case NETDEV_PRECHANGEUPPER:
 9993		break;
 9994	case NETDEV_CHANGEUPPER:
 9995		if (info->linking) {
 9996			struct netlink_ext_ack *extack;
 9997
 9998			extack = netdev_notifier_info_to_extack(&info->info);
 9999			err = mlxsw_sp_port_vrf_join(mlxsw_sp, l3_dev, extack);
10000		} else {
10001			mlxsw_sp_port_vrf_leave(mlxsw_sp, l3_dev);
10002		}
10003		break;
10004	}
10005
10006	return err;
10007}
10008
10009struct mlxsw_sp_router_replay_inetaddr_up {
10010	struct mlxsw_sp *mlxsw_sp;
10011	struct netlink_ext_ack *extack;
10012	unsigned int done;
10013	bool deslavement;
10014};
10015
10016static int mlxsw_sp_router_replay_inetaddr_up(struct net_device *dev,
10017					      struct netdev_nested_priv *priv)
10018{
10019	struct mlxsw_sp_router_replay_inetaddr_up *ctx = priv->data;
10020	bool nomaster = ctx->deslavement;
10021	struct mlxsw_sp_crif *crif;
10022	int err;
10023
10024	if (mlxsw_sp_dev_addr_list_empty(dev))
10025		return 0;
10026
10027	crif = mlxsw_sp_crif_lookup(ctx->mlxsw_sp->router, dev);
10028	if (!crif || crif->rif)
10029		return 0;
10030
10031	if (!mlxsw_sp_rif_should_config(crif->rif, dev, NETDEV_UP))
10032		return 0;
10033
10034	err = __mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_UP,
10035					nomaster, ctx->extack);
10036	if (err)
10037		return err;
10038
10039	ctx->done++;
10040	return 0;
10041}
10042
10043static int mlxsw_sp_router_unreplay_inetaddr_up(struct net_device *dev,
10044						struct netdev_nested_priv *priv)
10045{
10046	struct mlxsw_sp_router_replay_inetaddr_up *ctx = priv->data;
10047	bool nomaster = ctx->deslavement;
10048	struct mlxsw_sp_crif *crif;
10049
10050	if (!ctx->done)
10051		return 0;
10052
10053	if (mlxsw_sp_dev_addr_list_empty(dev))
10054		return 0;
10055
10056	crif = mlxsw_sp_crif_lookup(ctx->mlxsw_sp->router, dev);
10057	if (!crif || !crif->rif)
10058		return 0;
10059
10060	/* We are rolling back NETDEV_UP, so ask for that. */
10061	if (!mlxsw_sp_rif_should_config(crif->rif, dev, NETDEV_UP))
10062		return 0;
10063
10064	__mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_DOWN, nomaster,
10065				  NULL);
10066
10067	ctx->done--;
10068	return 0;
10069}
10070
10071int mlxsw_sp_netdevice_enslavement_replay(struct mlxsw_sp *mlxsw_sp,
10072					  struct net_device *upper_dev,
10073					  struct netlink_ext_ack *extack)
10074{
10075	struct mlxsw_sp_router_replay_inetaddr_up ctx = {
10076		.mlxsw_sp = mlxsw_sp,
10077		.extack = extack,
10078		.deslavement = false,
10079	};
10080	struct netdev_nested_priv priv = {
10081		.data = &ctx,
10082	};
10083	int err;
10084
10085	err = mlxsw_sp_router_replay_inetaddr_up(upper_dev, &priv);
10086	if (err)
10087		return err;
10088
10089	err = netdev_walk_all_upper_dev_rcu(upper_dev,
10090					    mlxsw_sp_router_replay_inetaddr_up,
10091					    &priv);
10092	if (err)
10093		goto err_replay_up;
10094
10095	return 0;
10096
10097err_replay_up:
10098	netdev_walk_all_upper_dev_rcu(upper_dev,
10099				      mlxsw_sp_router_unreplay_inetaddr_up,
10100				      &priv);
10101	mlxsw_sp_router_unreplay_inetaddr_up(upper_dev, &priv);
10102	return err;
10103}
10104
10105void mlxsw_sp_netdevice_deslavement_replay(struct mlxsw_sp *mlxsw_sp,
10106					   struct net_device *dev)
10107{
10108	struct mlxsw_sp_router_replay_inetaddr_up ctx = {
10109		.mlxsw_sp = mlxsw_sp,
10110		.deslavement = true,
10111	};
10112	struct netdev_nested_priv priv = {
10113		.data = &ctx,
10114	};
10115
10116	mlxsw_sp_router_replay_inetaddr_up(dev, &priv);
10117}
10118
10119static int
10120mlxsw_sp_port_vid_router_join_existing(struct mlxsw_sp_port *mlxsw_sp_port,
10121				       u16 vid, struct net_device *dev,
10122				       struct netlink_ext_ack *extack)
10123{
10124	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
10125
10126	mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port,
10127							    vid);
10128	if (WARN_ON(!mlxsw_sp_port_vlan))
10129		return -EINVAL;
10130
10131	return mlxsw_sp_port_vlan_router_join_existing(mlxsw_sp_port_vlan,
10132						       dev, extack);
10133}
10134
10135static void
10136mlxsw_sp_port_vid_router_leave(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
10137			       struct net_device *dev)
10138{
10139	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
10140
10141	mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port,
10142							    vid);
10143	if (WARN_ON(!mlxsw_sp_port_vlan))
10144		return;
10145
10146	__mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
10147}
10148
10149static int __mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port,
10150					   struct net_device *lag_dev,
10151					   struct netlink_ext_ack *extack)
10152{
10153	u16 default_vid = MLXSW_SP_DEFAULT_VID;
10154	struct net_device *upper_dev;
10155	struct list_head *iter;
10156	int done = 0;
10157	u16 vid;
10158	int err;
10159
10160	err = mlxsw_sp_port_vid_router_join_existing(mlxsw_sp_port, default_vid,
10161						     lag_dev, extack);
10162	if (err)
10163		return err;
10164
10165	netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) {
10166		if (!is_vlan_dev(upper_dev))
10167			continue;
10168
10169		vid = vlan_dev_vlan_id(upper_dev);
10170		err = mlxsw_sp_port_vid_router_join_existing(mlxsw_sp_port, vid,
10171							     upper_dev, extack);
10172		if (err)
10173			goto err_router_join_dev;
10174
10175		++done;
10176	}
10177
10178	return 0;
10179
10180err_router_join_dev:
10181	netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) {
10182		if (!is_vlan_dev(upper_dev))
10183			continue;
10184		if (!done--)
10185			break;
10186
10187		vid = vlan_dev_vlan_id(upper_dev);
10188		mlxsw_sp_port_vid_router_leave(mlxsw_sp_port, vid, upper_dev);
10189	}
10190
10191	mlxsw_sp_port_vid_router_leave(mlxsw_sp_port, default_vid, lag_dev);
10192	return err;
10193}
10194
10195static void
10196__mlxsw_sp_router_port_leave_lag(struct mlxsw_sp_port *mlxsw_sp_port,
10197				 struct net_device *lag_dev)
10198{
10199	u16 default_vid = MLXSW_SP_DEFAULT_VID;
10200	struct net_device *upper_dev;
10201	struct list_head *iter;
10202	u16 vid;
10203
10204	netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) {
10205		if (!is_vlan_dev(upper_dev))
10206			continue;
10207
10208		vid = vlan_dev_vlan_id(upper_dev);
10209		mlxsw_sp_port_vid_router_leave(mlxsw_sp_port, vid, upper_dev);
10210	}
10211
10212	mlxsw_sp_port_vid_router_leave(mlxsw_sp_port, default_vid, lag_dev);
10213}
10214
10215int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port,
10216				  struct net_device *lag_dev,
10217				  struct netlink_ext_ack *extack)
10218{
10219	int err;
10220
10221	mutex_lock(&mlxsw_sp_port->mlxsw_sp->router->lock);
10222	err = __mlxsw_sp_router_port_join_lag(mlxsw_sp_port, lag_dev, extack);
10223	mutex_unlock(&mlxsw_sp_port->mlxsw_sp->router->lock);
10224
10225	return err;
10226}
10227
10228void mlxsw_sp_router_port_leave_lag(struct mlxsw_sp_port *mlxsw_sp_port,
10229				    struct net_device *lag_dev)
10230{
10231	mutex_lock(&mlxsw_sp_port->mlxsw_sp->router->lock);
10232	__mlxsw_sp_router_port_leave_lag(mlxsw_sp_port, lag_dev);
10233	mutex_unlock(&mlxsw_sp_port->mlxsw_sp->router->lock);
10234}
10235
10236static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
10237					   unsigned long event, void *ptr)
10238{
10239	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
10240	struct mlxsw_sp_router *router;
10241	struct mlxsw_sp *mlxsw_sp;
10242	int err = 0;
10243
10244	router = container_of(nb, struct mlxsw_sp_router, netdevice_nb);
10245	mlxsw_sp = router->mlxsw_sp;
10246
10247	mutex_lock(&mlxsw_sp->router->lock);
10248
10249	if (event == NETDEV_REGISTER) {
10250		err = mlxsw_sp_netdevice_register(router, dev);
10251		if (err)
10252			/* No need to roll this back, UNREGISTER will collect it
10253			 * anyhow.
10254			 */
10255			goto out;
10256	}
10257
10258	if (mlxsw_sp_is_offload_xstats_event(event))
10259		err = mlxsw_sp_netdevice_offload_xstats_cmd(mlxsw_sp, dev,
10260							    event, ptr);
10261	else if (mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev))
10262		err = mlxsw_sp_netdevice_ipip_ol_event(mlxsw_sp, dev,
10263						       event, ptr);
10264	else if (mlxsw_sp_netdev_is_ipip_ul(mlxsw_sp, dev))
10265		err = mlxsw_sp_netdevice_ipip_ul_event(mlxsw_sp, dev,
10266						       event, ptr);
10267	else if (mlxsw_sp_is_router_event(event))
10268		err = mlxsw_sp_netdevice_router_port_event(dev, event, ptr);
10269	else if (mlxsw_sp_is_vrf_event(event, ptr))
10270		err = mlxsw_sp_netdevice_vrf_event(dev, event, ptr);
10271
10272	if (event == NETDEV_UNREGISTER)
10273		mlxsw_sp_netdevice_unregister(router, dev);
10274
10275out:
10276	mutex_unlock(&mlxsw_sp->router->lock);
10277
10278	return notifier_from_errno(err);
10279}
10280
10281struct mlxsw_sp_macvlan_replay {
10282	struct mlxsw_sp *mlxsw_sp;
10283	struct netlink_ext_ack *extack;
10284};
10285
10286static int mlxsw_sp_macvlan_replay_upper(struct net_device *dev,
10287					 struct netdev_nested_priv *priv)
10288{
10289	const struct mlxsw_sp_macvlan_replay *rms = priv->data;
10290	struct netlink_ext_ack *extack = rms->extack;
10291	struct mlxsw_sp *mlxsw_sp = rms->mlxsw_sp;
10292
10293	if (!netif_is_macvlan(dev))
10294		return 0;
10295
10296	return mlxsw_sp_rif_macvlan_add(mlxsw_sp, dev, extack);
10297}
10298
10299static int mlxsw_sp_macvlan_replay(struct mlxsw_sp_rif *rif,
10300				   struct netlink_ext_ack *extack)
10301{
10302	struct mlxsw_sp_macvlan_replay rms = {
10303		.mlxsw_sp = rif->mlxsw_sp,
10304		.extack = extack,
10305	};
10306	struct netdev_nested_priv priv = {
10307		.data = &rms,
10308	};
10309
10310	return netdev_walk_all_upper_dev_rcu(mlxsw_sp_rif_dev(rif),
10311					     mlxsw_sp_macvlan_replay_upper,
10312					     &priv);
10313}
10314
10315static int __mlxsw_sp_rif_macvlan_flush(struct net_device *dev,
10316					struct netdev_nested_priv *priv)
10317{
10318	struct mlxsw_sp_rif *rif = (struct mlxsw_sp_rif *)priv->data;
10319
10320	if (!netif_is_macvlan(dev))
10321		return 0;
10322
10323	return mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
10324				   mlxsw_sp_fid_index(rif->fid), false);
10325}
10326
10327static int mlxsw_sp_rif_macvlan_flush(struct mlxsw_sp_rif *rif)
10328{
10329	struct net_device *dev = mlxsw_sp_rif_dev(rif);
10330	struct netdev_nested_priv priv = {
10331		.data = (void *)rif,
10332	};
10333
10334	if (!netif_is_macvlan_port(dev))
10335		return 0;
10336
10337	return netdev_walk_all_upper_dev_rcu(dev,
10338					     __mlxsw_sp_rif_macvlan_flush, &priv);
10339}
10340
10341static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif *rif,
10342				       const struct mlxsw_sp_rif_params *params)
10343{
10344	struct mlxsw_sp_rif_subport *rif_subport;
10345
10346	rif_subport = mlxsw_sp_rif_subport_rif(rif);
10347	refcount_set(&rif_subport->ref_count, 1);
10348	rif_subport->vid = params->vid;
10349	rif_subport->lag = params->lag;
10350	if (params->lag)
10351		rif_subport->lag_id = params->lag_id;
10352	else
10353		rif_subport->system_port = params->system_port;
10354}
10355
10356static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable)
10357{
10358	struct net_device *dev = mlxsw_sp_rif_dev(rif);
10359	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
10360	struct mlxsw_sp_rif_subport *rif_subport;
10361	char ritr_pl[MLXSW_REG_RITR_LEN];
10362	u16 efid;
10363
10364	rif_subport = mlxsw_sp_rif_subport_rif(rif);
10365	mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_SP_IF,
10366			    rif->rif_index, rif->vr_id, dev->mtu);
10367	mlxsw_reg_ritr_mac_pack(ritr_pl, dev->dev_addr);
10368	mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id);
10369	efid = mlxsw_sp_fid_index(rif->fid);
10370	mlxsw_reg_ritr_sp_if_pack(ritr_pl, rif_subport->lag,
10371				  rif_subport->lag ? rif_subport->lag_id :
10372						     rif_subport->system_port,
10373				  efid, 0);
10374	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
10375}
10376
10377static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif,
10378					  struct netlink_ext_ack *extack)
10379{
10380	struct net_device *dev = mlxsw_sp_rif_dev(rif);
10381	u8 mac_profile;
10382	int err;
10383
10384	err = mlxsw_sp_rif_mac_profile_get(rif->mlxsw_sp, rif->addr,
10385					   &mac_profile, extack);
10386	if (err)
10387		return err;
10388	rif->mac_profile_id = mac_profile;
10389
10390	err = mlxsw_sp_rif_subport_op(rif, true);
10391	if (err)
10392		goto err_rif_subport_op;
10393
10394	err = mlxsw_sp_macvlan_replay(rif, extack);
10395	if (err)
10396		goto err_macvlan_replay;
10397
10398	err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
10399				  mlxsw_sp_fid_index(rif->fid), true);
10400	if (err)
10401		goto err_rif_fdb_op;
10402
10403	err = mlxsw_sp_fid_rif_set(rif->fid, rif);
10404	if (err)
10405		goto err_fid_rif_set;
10406
10407	return 0;
10408
10409err_fid_rif_set:
10410	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
10411			    mlxsw_sp_fid_index(rif->fid), false);
10412err_rif_fdb_op:
10413	mlxsw_sp_rif_macvlan_flush(rif);
10414err_macvlan_replay:
10415	mlxsw_sp_rif_subport_op(rif, false);
10416err_rif_subport_op:
10417	mlxsw_sp_rif_mac_profile_put(rif->mlxsw_sp, mac_profile);
10418	return err;
10419}
10420
10421static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif *rif)
10422{
10423	struct net_device *dev = mlxsw_sp_rif_dev(rif);
10424	struct mlxsw_sp_fid *fid = rif->fid;
10425
10426	mlxsw_sp_fid_rif_unset(fid);
10427	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
10428			    mlxsw_sp_fid_index(fid), false);
10429	mlxsw_sp_rif_macvlan_flush(rif);
10430	mlxsw_sp_rif_subport_op(rif, false);
10431	mlxsw_sp_rif_mac_profile_put(rif->mlxsw_sp, rif->mac_profile_id);
10432}
10433
10434static struct mlxsw_sp_fid *
10435mlxsw_sp_rif_subport_fid_get(struct mlxsw_sp_rif *rif,
10436			     const struct mlxsw_sp_rif_params *params,
10437			     struct netlink_ext_ack *extack)
10438{
10439	return mlxsw_sp_fid_rfid_get(rif->mlxsw_sp, rif->rif_index);
10440}
10441
10442static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops = {
10443	.type			= MLXSW_SP_RIF_TYPE_SUBPORT,
10444	.rif_size		= sizeof(struct mlxsw_sp_rif_subport),
10445	.setup			= mlxsw_sp_rif_subport_setup,
10446	.configure		= mlxsw_sp_rif_subport_configure,
10447	.deconfigure		= mlxsw_sp_rif_subport_deconfigure,
10448	.fid_get		= mlxsw_sp_rif_subport_fid_get,
10449};
10450
10451static int mlxsw_sp_rif_fid_op(struct mlxsw_sp_rif *rif, u16 fid, bool enable)
10452{
10453	enum mlxsw_reg_ritr_if_type type = MLXSW_REG_RITR_FID_IF;
10454	struct net_device *dev = mlxsw_sp_rif_dev(rif);
10455	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
10456	char ritr_pl[MLXSW_REG_RITR_LEN];
10457
10458	mlxsw_reg_ritr_pack(ritr_pl, enable, type, rif->rif_index, rif->vr_id,
10459			    dev->mtu);
10460	mlxsw_reg_ritr_mac_pack(ritr_pl, dev->dev_addr);
10461	mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id);
10462	mlxsw_reg_ritr_fid_if_fid_set(ritr_pl, fid);
10463
10464	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
10465}
10466
10467u16 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp)
10468{
10469	return mlxsw_core_max_ports(mlxsw_sp->core) + 1;
10470}
10471
10472static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif,
10473				      struct netlink_ext_ack *extack)
10474{
10475	struct net_device *dev = mlxsw_sp_rif_dev(rif);
10476	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
10477	u16 fid_index = mlxsw_sp_fid_index(rif->fid);
10478	u8 mac_profile;
10479	int err;
10480
10481	err = mlxsw_sp_rif_mac_profile_get(mlxsw_sp, rif->addr,
10482					   &mac_profile, extack);
10483	if (err)
10484		return err;
10485	rif->mac_profile_id = mac_profile;
10486
10487	err = mlxsw_sp_rif_fid_op(rif, fid_index, true);
10488	if (err)
10489		goto err_rif_fid_op;
10490
10491	err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
10492				     mlxsw_sp_router_port(mlxsw_sp), true);
10493	if (err)
10494		goto err_fid_mc_flood_set;
10495
10496	err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
10497				     mlxsw_sp_router_port(mlxsw_sp), true);
10498	if (err)
10499		goto err_fid_bc_flood_set;
10500
10501	err = mlxsw_sp_macvlan_replay(rif, extack);
10502	if (err)
10503		goto err_macvlan_replay;
10504
10505	err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
10506				  mlxsw_sp_fid_index(rif->fid), true);
10507	if (err)
10508		goto err_rif_fdb_op;
10509
10510	err = mlxsw_sp_fid_rif_set(rif->fid, rif);
10511	if (err)
10512		goto err_fid_rif_set;
10513
10514	return 0;
10515
10516err_fid_rif_set:
10517	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
10518			    mlxsw_sp_fid_index(rif->fid), false);
10519err_rif_fdb_op:
10520	mlxsw_sp_rif_macvlan_flush(rif);
10521err_macvlan_replay:
10522	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
10523			       mlxsw_sp_router_port(mlxsw_sp), false);
10524err_fid_bc_flood_set:
10525	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
10526			       mlxsw_sp_router_port(mlxsw_sp), false);
10527err_fid_mc_flood_set:
10528	mlxsw_sp_rif_fid_op(rif, fid_index, false);
10529err_rif_fid_op:
10530	mlxsw_sp_rif_mac_profile_put(mlxsw_sp, mac_profile);
10531	return err;
10532}
10533
10534static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif *rif)
10535{
10536	struct net_device *dev = mlxsw_sp_rif_dev(rif);
10537	u16 fid_index = mlxsw_sp_fid_index(rif->fid);
10538	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
10539	struct mlxsw_sp_fid *fid = rif->fid;
10540
10541	mlxsw_sp_fid_rif_unset(fid);
10542	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
10543			    mlxsw_sp_fid_index(fid), false);
10544	mlxsw_sp_rif_macvlan_flush(rif);
10545	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
10546			       mlxsw_sp_router_port(mlxsw_sp), false);
10547	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
10548			       mlxsw_sp_router_port(mlxsw_sp), false);
10549	mlxsw_sp_rif_fid_op(rif, fid_index, false);
10550	mlxsw_sp_rif_mac_profile_put(rif->mlxsw_sp, rif->mac_profile_id);
10551}
10552
10553static struct mlxsw_sp_fid *
10554mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif,
10555			 const struct mlxsw_sp_rif_params *params,
10556			 struct netlink_ext_ack *extack)
10557{
10558	int rif_ifindex = mlxsw_sp_rif_dev_ifindex(rif);
10559
10560	return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif_ifindex);
10561}
10562
10563static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
10564{
10565	struct switchdev_notifier_fdb_info info = {};
10566	struct net_device *dev;
10567
10568	dev = br_fdb_find_port(mlxsw_sp_rif_dev(rif), mac, 0);
10569	if (!dev)
10570		return;
10571
10572	info.addr = mac;
10573	info.vid = 0;
10574	call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info,
10575				 NULL);
10576}
10577
10578static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops = {
10579	.type			= MLXSW_SP_RIF_TYPE_FID,
10580	.rif_size		= sizeof(struct mlxsw_sp_rif),
10581	.configure		= mlxsw_sp_rif_fid_configure,
10582	.deconfigure		= mlxsw_sp_rif_fid_deconfigure,
10583	.fid_get		= mlxsw_sp_rif_fid_fid_get,
10584	.fdb_del		= mlxsw_sp_rif_fid_fdb_del,
10585};
10586
10587static struct mlxsw_sp_fid *
10588mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif,
10589			  const struct mlxsw_sp_rif_params *params,
10590			  struct netlink_ext_ack *extack)
10591{
10592	struct net_device *dev = mlxsw_sp_rif_dev(rif);
10593	struct net_device *br_dev;
10594
10595	if (WARN_ON(!params->vid))
10596		return ERR_PTR(-EINVAL);
10597
10598	if (is_vlan_dev(dev)) {
10599		br_dev = vlan_dev_real_dev(dev);
10600		if (WARN_ON(!netif_is_bridge_master(br_dev)))
10601			return ERR_PTR(-EINVAL);
10602	}
10603
10604	return mlxsw_sp_fid_8021q_get(rif->mlxsw_sp, params->vid);
10605}
10606
10607static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
10608{
10609	struct net_device *rif_dev = mlxsw_sp_rif_dev(rif);
10610	struct switchdev_notifier_fdb_info info = {};
10611	u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
10612	struct net_device *br_dev;
10613	struct net_device *dev;
10614
10615	br_dev = is_vlan_dev(rif_dev) ? vlan_dev_real_dev(rif_dev) : rif_dev;
10616	dev = br_fdb_find_port(br_dev, mac, vid);
10617	if (!dev)
10618		return;
10619
10620	info.addr = mac;
10621	info.vid = vid;
10622	call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info,
10623				 NULL);
10624}
10625
10626static int mlxsw_sp_rif_vlan_op(struct mlxsw_sp_rif *rif, u16 vid, u16 efid,
10627				bool enable)
10628{
10629	struct net_device *dev = mlxsw_sp_rif_dev(rif);
10630	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
10631	char ritr_pl[MLXSW_REG_RITR_LEN];
10632
10633	mlxsw_reg_ritr_vlan_if_pack(ritr_pl, enable, rif->rif_index, rif->vr_id,
10634				    dev->mtu, dev->dev_addr,
10635				    rif->mac_profile_id, vid, efid);
10636
10637	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
10638}
10639
10640static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid,
10641				       struct netlink_ext_ack *extack)
10642{
10643	struct net_device *dev = mlxsw_sp_rif_dev(rif);
10644	u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
10645	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
10646	u8 mac_profile;
10647	int err;
10648
10649	err = mlxsw_sp_rif_mac_profile_get(mlxsw_sp, rif->addr,
10650					   &mac_profile, extack);
10651	if (err)
10652		return err;
10653	rif->mac_profile_id = mac_profile;
10654
10655	err = mlxsw_sp_rif_vlan_op(rif, vid, efid, true);
10656	if (err)
10657		goto err_rif_vlan_fid_op;
10658
10659	err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
10660				     mlxsw_sp_router_port(mlxsw_sp), true);
10661	if (err)
10662		goto err_fid_mc_flood_set;
10663
10664	err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
10665				     mlxsw_sp_router_port(mlxsw_sp), true);
10666	if (err)
10667		goto err_fid_bc_flood_set;
10668
10669	err = mlxsw_sp_macvlan_replay(rif, extack);
10670	if (err)
10671		goto err_macvlan_replay;
10672
10673	err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
10674				  mlxsw_sp_fid_index(rif->fid), true);
10675	if (err)
10676		goto err_rif_fdb_op;
10677
10678	err = mlxsw_sp_fid_rif_set(rif->fid, rif);
10679	if (err)
10680		goto err_fid_rif_set;
10681
10682	return 0;
10683
10684err_fid_rif_set:
10685	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
10686			    mlxsw_sp_fid_index(rif->fid), false);
10687err_rif_fdb_op:
10688	mlxsw_sp_rif_macvlan_flush(rif);
10689err_macvlan_replay:
10690	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
10691			       mlxsw_sp_router_port(mlxsw_sp), false);
10692err_fid_bc_flood_set:
10693	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
10694			       mlxsw_sp_router_port(mlxsw_sp), false);
10695err_fid_mc_flood_set:
10696	mlxsw_sp_rif_vlan_op(rif, vid, 0, false);
10697err_rif_vlan_fid_op:
10698	mlxsw_sp_rif_mac_profile_put(mlxsw_sp, mac_profile);
10699	return err;
10700}
10701
10702static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif *rif)
10703{
10704	struct net_device *dev = mlxsw_sp_rif_dev(rif);
10705	u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
10706	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
10707
10708	mlxsw_sp_fid_rif_unset(rif->fid);
10709	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
10710			    mlxsw_sp_fid_index(rif->fid), false);
10711	mlxsw_sp_rif_macvlan_flush(rif);
10712	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
10713			       mlxsw_sp_router_port(mlxsw_sp), false);
10714	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
10715			       mlxsw_sp_router_port(mlxsw_sp), false);
10716	mlxsw_sp_rif_vlan_op(rif, vid, 0, false);
10717	mlxsw_sp_rif_mac_profile_put(rif->mlxsw_sp, rif->mac_profile_id);
10718}
10719
10720static int mlxsw_sp1_rif_vlan_configure(struct mlxsw_sp_rif *rif,
10721					struct netlink_ext_ack *extack)
10722{
10723	return mlxsw_sp_rif_vlan_configure(rif, 0, extack);
10724}
10725
10726static const struct mlxsw_sp_rif_ops mlxsw_sp1_rif_vlan_ops = {
10727	.type			= MLXSW_SP_RIF_TYPE_VLAN,
10728	.rif_size		= sizeof(struct mlxsw_sp_rif),
10729	.configure		= mlxsw_sp1_rif_vlan_configure,
10730	.deconfigure		= mlxsw_sp_rif_vlan_deconfigure,
10731	.fid_get		= mlxsw_sp_rif_vlan_fid_get,
10732	.fdb_del		= mlxsw_sp_rif_vlan_fdb_del,
10733};
10734
10735static int mlxsw_sp2_rif_vlan_configure(struct mlxsw_sp_rif *rif,
10736					struct netlink_ext_ack *extack)
10737{
10738	u16 efid = mlxsw_sp_fid_index(rif->fid);
10739
10740	return mlxsw_sp_rif_vlan_configure(rif, efid, extack);
10741}
10742
10743static const struct mlxsw_sp_rif_ops mlxsw_sp2_rif_vlan_ops = {
10744	.type			= MLXSW_SP_RIF_TYPE_VLAN,
10745	.rif_size		= sizeof(struct mlxsw_sp_rif),
10746	.configure		= mlxsw_sp2_rif_vlan_configure,
10747	.deconfigure		= mlxsw_sp_rif_vlan_deconfigure,
10748	.fid_get		= mlxsw_sp_rif_vlan_fid_get,
10749	.fdb_del		= mlxsw_sp_rif_vlan_fdb_del,
10750};
10751
10752static struct mlxsw_sp_rif_ipip_lb *
10753mlxsw_sp_rif_ipip_lb_rif(struct mlxsw_sp_rif *rif)
10754{
10755	return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common);
10756}
10757
10758static void
10759mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif *rif,
10760			   const struct mlxsw_sp_rif_params *params)
10761{
10762	struct mlxsw_sp_rif_params_ipip_lb *params_lb;
10763	struct mlxsw_sp_rif_ipip_lb *rif_lb;
10764
10765	params_lb = container_of(params, struct mlxsw_sp_rif_params_ipip_lb,
10766				 common);
10767	rif_lb = mlxsw_sp_rif_ipip_lb_rif(rif);
10768	rif_lb->lb_config = params_lb->lb_config;
10769}
10770
10771static int
10772mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif,
10773				struct netlink_ext_ack *extack)
10774{
10775	struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
10776	struct net_device *dev = mlxsw_sp_rif_dev(rif);
10777	u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev);
10778	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
10779	struct mlxsw_sp_vr *ul_vr;
10780	int err;
10781
10782	ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id, extack);
10783	if (IS_ERR(ul_vr))
10784		return PTR_ERR(ul_vr);
10785
10786	err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr->id, 0, true);
10787	if (err)
10788		goto err_loopback_op;
10789
10790	lb_rif->ul_vr_id = ul_vr->id;
10791	lb_rif->ul_rif_id = 0;
10792	++ul_vr->rif_count;
10793	return 0;
10794
10795err_loopback_op:
10796	mlxsw_sp_vr_put(mlxsw_sp, ul_vr);
10797	return err;
10798}
10799
10800static void mlxsw_sp1_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif)
10801{
10802	struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
10803	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
10804	struct mlxsw_sp_vr *ul_vr;
10805
10806	ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id];
10807	mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr->id, 0, false);
10808
10809	--ul_vr->rif_count;
10810	mlxsw_sp_vr_put(mlxsw_sp, ul_vr);
10811}
10812
10813static const struct mlxsw_sp_rif_ops mlxsw_sp1_rif_ipip_lb_ops = {
10814	.type			= MLXSW_SP_RIF_TYPE_IPIP_LB,
10815	.rif_size		= sizeof(struct mlxsw_sp_rif_ipip_lb),
10816	.setup                  = mlxsw_sp_rif_ipip_lb_setup,
10817	.configure		= mlxsw_sp1_rif_ipip_lb_configure,
10818	.deconfigure		= mlxsw_sp1_rif_ipip_lb_deconfigure,
10819};
10820
10821static const struct mlxsw_sp_rif_ops *mlxsw_sp1_rif_ops_arr[] = {
10822	[MLXSW_SP_RIF_TYPE_SUBPORT]	= &mlxsw_sp_rif_subport_ops,
10823	[MLXSW_SP_RIF_TYPE_VLAN]	= &mlxsw_sp1_rif_vlan_ops,
10824	[MLXSW_SP_RIF_TYPE_FID]		= &mlxsw_sp_rif_fid_ops,
10825	[MLXSW_SP_RIF_TYPE_IPIP_LB]	= &mlxsw_sp1_rif_ipip_lb_ops,
10826};
10827
10828static int
10829mlxsw_sp_rif_ipip_lb_ul_rif_op(struct mlxsw_sp_rif *ul_rif, bool enable)
10830{
10831	struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp;
10832	char ritr_pl[MLXSW_REG_RITR_LEN];
10833
10834	mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
10835			    ul_rif->rif_index, ul_rif->vr_id, IP_MAX_MTU);
10836	mlxsw_reg_ritr_loopback_protocol_set(ritr_pl,
10837					     MLXSW_REG_RITR_LOOPBACK_GENERIC);
10838
10839	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
10840}
10841
10842static struct mlxsw_sp_rif *
10843mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
10844		       struct mlxsw_sp_crif *ul_crif,
10845		       struct netlink_ext_ack *extack)
10846{
10847	struct mlxsw_sp_rif *ul_rif;
10848	u8 rif_entries = 1;
10849	u16 rif_index;
10850	int err;
10851
10852	err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index, rif_entries);
10853	if (err) {
10854		NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported router interfaces");
10855		return ERR_PTR(err);
10856	}
10857
10858	ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id,
10859				    ul_crif);
10860	if (!ul_rif) {
10861		err = -ENOMEM;
10862		goto err_rif_alloc;
10863	}
10864
10865	mlxsw_sp->router->rifs[rif_index] = ul_rif;
10866	ul_rif->mlxsw_sp = mlxsw_sp;
10867	ul_rif->rif_entries = rif_entries;
10868	err = mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, true);
10869	if (err)
10870		goto ul_rif_op_err;
10871
10872	atomic_add(rif_entries, &mlxsw_sp->router->rifs_count);
10873	return ul_rif;
10874
10875ul_rif_op_err:
10876	mlxsw_sp->router->rifs[rif_index] = NULL;
10877	mlxsw_sp_rif_free(ul_rif);
10878err_rif_alloc:
10879	mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
10880	return ERR_PTR(err);
10881}
10882
10883static void mlxsw_sp_ul_rif_destroy(struct mlxsw_sp_rif *ul_rif)
10884{
10885	struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp;
10886	u8 rif_entries = ul_rif->rif_entries;
10887	u16 rif_index = ul_rif->rif_index;
10888
10889	atomic_sub(rif_entries, &mlxsw_sp->router->rifs_count);
10890	mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, false);
10891	mlxsw_sp->router->rifs[ul_rif->rif_index] = NULL;
10892	mlxsw_sp_rif_free(ul_rif);
10893	mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
10894}
10895
10896static struct mlxsw_sp_rif *
10897mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
10898		    struct mlxsw_sp_crif *ul_crif,
10899		    struct netlink_ext_ack *extack)
10900{
10901	struct mlxsw_sp_vr *vr;
10902	int err;
10903
10904	vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id, extack);
10905	if (IS_ERR(vr))
10906		return ERR_CAST(vr);
10907
10908	if (refcount_inc_not_zero(&vr->ul_rif_refcnt))
10909		return vr->ul_rif;
10910
10911	vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, ul_crif, extack);
10912	if (IS_ERR(vr->ul_rif)) {
10913		err = PTR_ERR(vr->ul_rif);
10914		goto err_ul_rif_create;
10915	}
10916
10917	vr->rif_count++;
10918	refcount_set(&vr->ul_rif_refcnt, 1);
10919
10920	return vr->ul_rif;
10921
10922err_ul_rif_create:
10923	mlxsw_sp_vr_put(mlxsw_sp, vr);
10924	return ERR_PTR(err);
10925}
10926
10927static void mlxsw_sp_ul_rif_put(struct mlxsw_sp_rif *ul_rif)
10928{
10929	struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp;
10930	struct mlxsw_sp_vr *vr;
10931
10932	vr = &mlxsw_sp->router->vrs[ul_rif->vr_id];
10933
10934	if (!refcount_dec_and_test(&vr->ul_rif_refcnt))
10935		return;
10936
10937	vr->rif_count--;
10938	mlxsw_sp_ul_rif_destroy(ul_rif);
10939	mlxsw_sp_vr_put(mlxsw_sp, vr);
10940}
10941
10942int mlxsw_sp_router_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
10943			       u16 *ul_rif_index)
10944{
10945	struct mlxsw_sp_rif *ul_rif;
10946	int err = 0;
10947
10948	mutex_lock(&mlxsw_sp->router->lock);
10949	ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL, NULL);
10950	if (IS_ERR(ul_rif)) {
10951		err = PTR_ERR(ul_rif);
10952		goto out;
10953	}
10954	*ul_rif_index = ul_rif->rif_index;
10955out:
10956	mutex_unlock(&mlxsw_sp->router->lock);
10957	return err;
10958}
10959
10960void mlxsw_sp_router_ul_rif_put(struct mlxsw_sp *mlxsw_sp, u16 ul_rif_index)
10961{
10962	struct mlxsw_sp_rif *ul_rif;
10963
10964	mutex_lock(&mlxsw_sp->router->lock);
10965	ul_rif = mlxsw_sp->router->rifs[ul_rif_index];
10966	if (WARN_ON(!ul_rif))
10967		goto out;
10968
10969	mlxsw_sp_ul_rif_put(ul_rif);
10970out:
10971	mutex_unlock(&mlxsw_sp->router->lock);
10972}
10973
10974static int
10975mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif,
10976				struct netlink_ext_ack *extack)
10977{
10978	struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
10979	struct net_device *dev = mlxsw_sp_rif_dev(rif);
10980	u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev);
10981	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
10982	struct mlxsw_sp_rif *ul_rif;
10983	int err;
10984
10985	ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL, extack);
10986	if (IS_ERR(ul_rif))
10987		return PTR_ERR(ul_rif);
10988
10989	err = mlxsw_sp_rif_ipip_lb_op(lb_rif, 0, ul_rif->rif_index, true);
10990	if (err)
10991		goto err_loopback_op;
10992
10993	lb_rif->ul_vr_id = 0;
10994	lb_rif->ul_rif_id = ul_rif->rif_index;
10995
10996	return 0;
10997
10998err_loopback_op:
10999	mlxsw_sp_ul_rif_put(ul_rif);
11000	return err;
11001}
11002
11003static void mlxsw_sp2_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif)
11004{
11005	struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
11006	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
11007	struct mlxsw_sp_rif *ul_rif;
11008
11009	ul_rif = mlxsw_sp_rif_by_index(mlxsw_sp, lb_rif->ul_rif_id);
11010	mlxsw_sp_rif_ipip_lb_op(lb_rif, 0, lb_rif->ul_rif_id, false);
11011	mlxsw_sp_ul_rif_put(ul_rif);
11012}
11013
11014static const struct mlxsw_sp_rif_ops mlxsw_sp2_rif_ipip_lb_ops = {
11015	.type			= MLXSW_SP_RIF_TYPE_IPIP_LB,
11016	.rif_size		= sizeof(struct mlxsw_sp_rif_ipip_lb),
11017	.setup                  = mlxsw_sp_rif_ipip_lb_setup,
11018	.configure		= mlxsw_sp2_rif_ipip_lb_configure,
11019	.deconfigure		= mlxsw_sp2_rif_ipip_lb_deconfigure,
11020};
11021
11022static const struct mlxsw_sp_rif_ops *mlxsw_sp2_rif_ops_arr[] = {
11023	[MLXSW_SP_RIF_TYPE_SUBPORT]	= &mlxsw_sp_rif_subport_ops,
11024	[MLXSW_SP_RIF_TYPE_VLAN]	= &mlxsw_sp2_rif_vlan_ops,
11025	[MLXSW_SP_RIF_TYPE_FID]		= &mlxsw_sp_rif_fid_ops,
11026	[MLXSW_SP_RIF_TYPE_IPIP_LB]	= &mlxsw_sp2_rif_ipip_lb_ops,
11027};
11028
11029static int mlxsw_sp_rifs_table_init(struct mlxsw_sp *mlxsw_sp)
11030{
11031	struct gen_pool *rifs_table;
11032	int err;
11033
11034	rifs_table = gen_pool_create(0, -1);
11035	if (!rifs_table)
11036		return -ENOMEM;
11037
11038	gen_pool_set_algo(rifs_table, gen_pool_first_fit_order_align,
11039			  NULL);
11040
11041	err = gen_pool_add(rifs_table, MLXSW_SP_ROUTER_GENALLOC_OFFSET,
11042			   MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS), -1);
11043	if (err)
11044		goto err_gen_pool_add;
11045
11046	mlxsw_sp->router->rifs_table = rifs_table;
11047
11048	return 0;
11049
11050err_gen_pool_add:
11051	gen_pool_destroy(rifs_table);
11052	return err;
11053}
11054
11055static void mlxsw_sp_rifs_table_fini(struct mlxsw_sp *mlxsw_sp)
11056{
11057	gen_pool_destroy(mlxsw_sp->router->rifs_table);
11058}
11059
11060static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp)
11061{
11062	u64 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
11063	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
11064	struct mlxsw_core *core = mlxsw_sp->core;
11065	int err;
11066
11067	if (!MLXSW_CORE_RES_VALID(core, MAX_RIF_MAC_PROFILES))
11068		return -EIO;
11069	mlxsw_sp->router->max_rif_mac_profile =
11070		MLXSW_CORE_RES_GET(core, MAX_RIF_MAC_PROFILES);
11071
11072	mlxsw_sp->router->rifs = kcalloc(max_rifs,
11073					 sizeof(struct mlxsw_sp_rif *),
11074					 GFP_KERNEL);
11075	if (!mlxsw_sp->router->rifs)
11076		return -ENOMEM;
11077
11078	err = mlxsw_sp_rifs_table_init(mlxsw_sp);
11079	if (err)
11080		goto err_rifs_table_init;
11081
11082	idr_init(&mlxsw_sp->router->rif_mac_profiles_idr);
11083	atomic_set(&mlxsw_sp->router->rif_mac_profiles_count, 0);
11084	atomic_set(&mlxsw_sp->router->rifs_count, 0);
11085	devl_resource_occ_get_register(devlink,
11086				       MLXSW_SP_RESOURCE_RIF_MAC_PROFILES,
11087				       mlxsw_sp_rif_mac_profiles_occ_get,
11088				       mlxsw_sp);
11089	devl_resource_occ_get_register(devlink,
11090				       MLXSW_SP_RESOURCE_RIFS,
11091				       mlxsw_sp_rifs_occ_get,
11092				       mlxsw_sp);
11093
11094	return 0;
11095
11096err_rifs_table_init:
11097	kfree(mlxsw_sp->router->rifs);
11098	return err;
11099}
11100
11101static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp)
11102{
11103	int max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
11104	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
11105	int i;
11106
11107	WARN_ON_ONCE(atomic_read(&mlxsw_sp->router->rifs_count));
11108	for (i = 0; i < max_rifs; i++)
11109		WARN_ON_ONCE(mlxsw_sp->router->rifs[i]);
11110
11111	devl_resource_occ_get_unregister(devlink, MLXSW_SP_RESOURCE_RIFS);
11112	devl_resource_occ_get_unregister(devlink,
11113					 MLXSW_SP_RESOURCE_RIF_MAC_PROFILES);
11114	WARN_ON(!idr_is_empty(&mlxsw_sp->router->rif_mac_profiles_idr));
11115	idr_destroy(&mlxsw_sp->router->rif_mac_profiles_idr);
11116	mlxsw_sp_rifs_table_fini(mlxsw_sp);
11117	kfree(mlxsw_sp->router->rifs);
11118}
11119
11120static int
11121mlxsw_sp_ipip_config_tigcr(struct mlxsw_sp *mlxsw_sp)
11122{
11123	char tigcr_pl[MLXSW_REG_TIGCR_LEN];
11124
11125	mlxsw_reg_tigcr_pack(tigcr_pl, true, 0);
11126	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tigcr), tigcr_pl);
11127}
11128
11129static int mlxsw_sp_ipips_init(struct mlxsw_sp *mlxsw_sp)
11130{
11131	int err;
11132
11133	INIT_LIST_HEAD(&mlxsw_sp->router->ipip_list);
11134
11135	err = mlxsw_sp_ipip_ecn_encap_init(mlxsw_sp);
11136	if (err)
11137		return err;
11138	err = mlxsw_sp_ipip_ecn_decap_init(mlxsw_sp);
11139	if (err)
11140		return err;
11141
11142	return mlxsw_sp_ipip_config_tigcr(mlxsw_sp);
11143}
11144
11145static int mlxsw_sp1_ipips_init(struct mlxsw_sp *mlxsw_sp)
11146{
11147	mlxsw_sp->router->ipip_ops_arr = mlxsw_sp1_ipip_ops_arr;
11148	return mlxsw_sp_ipips_init(mlxsw_sp);
11149}
11150
11151static int mlxsw_sp2_ipips_init(struct mlxsw_sp *mlxsw_sp)
11152{
11153	mlxsw_sp->router->ipip_ops_arr = mlxsw_sp2_ipip_ops_arr;
11154	return mlxsw_sp_ipips_init(mlxsw_sp);
11155}
11156
11157static void mlxsw_sp_ipips_fini(struct mlxsw_sp *mlxsw_sp)
11158{
11159	WARN_ON(!list_empty(&mlxsw_sp->router->ipip_list));
11160}
11161
11162static void mlxsw_sp_router_fib_dump_flush(struct notifier_block *nb)
11163{
11164	struct mlxsw_sp_router *router;
11165
11166	/* Flush pending FIB notifications and then flush the device's
11167	 * table before requesting another dump. The FIB notification
11168	 * block is unregistered, so no need to take RTNL.
11169	 */
11170	mlxsw_core_flush_owq();
11171	router = container_of(nb, struct mlxsw_sp_router, fib_nb);
11172	mlxsw_sp_router_fib_flush(router->mlxsw_sp);
11173}
11174
11175#ifdef CONFIG_IP_ROUTE_MULTIPATH
11176struct mlxsw_sp_mp_hash_config {
11177	DECLARE_BITMAP(headers, __MLXSW_REG_RECR2_HEADER_CNT);
11178	DECLARE_BITMAP(fields, __MLXSW_REG_RECR2_FIELD_CNT);
11179	DECLARE_BITMAP(inner_headers, __MLXSW_REG_RECR2_HEADER_CNT);
11180	DECLARE_BITMAP(inner_fields, __MLXSW_REG_RECR2_INNER_FIELD_CNT);
11181	bool inc_parsing_depth;
11182};
11183
11184#define MLXSW_SP_MP_HASH_HEADER_SET(_headers, _header) \
11185	bitmap_set(_headers, MLXSW_REG_RECR2_##_header, 1)
11186
11187#define MLXSW_SP_MP_HASH_FIELD_SET(_fields, _field) \
11188	bitmap_set(_fields, MLXSW_REG_RECR2_##_field, 1)
11189
11190#define MLXSW_SP_MP_HASH_FIELD_RANGE_SET(_fields, _field, _nr) \
11191	bitmap_set(_fields, MLXSW_REG_RECR2_##_field, _nr)
11192
11193static void mlxsw_sp_mp_hash_inner_l3(struct mlxsw_sp_mp_hash_config *config)
11194{
11195	unsigned long *inner_headers = config->inner_headers;
11196	unsigned long *inner_fields = config->inner_fields;
11197
11198	/* IPv4 inner */
11199	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV4_EN_NOT_TCP_NOT_UDP);
11200	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV4_EN_TCP_UDP);
11201	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV4_SIP0, 4);
11202	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV4_DIP0, 4);
11203	/* IPv6 inner */
11204	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV6_EN_NOT_TCP_NOT_UDP);
11205	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV6_EN_TCP_UDP);
11206	MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_SIP0_7);
11207	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV6_SIP8, 8);
11208	MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_DIP0_7);
11209	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV6_DIP8, 8);
11210	MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_NEXT_HEADER);
11211	MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_FLOW_LABEL);
11212}
11213
11214static void mlxsw_sp_mp4_hash_outer_addr(struct mlxsw_sp_mp_hash_config *config)
11215{
11216	unsigned long *headers = config->headers;
11217	unsigned long *fields = config->fields;
11218
11219	MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV4_EN_NOT_TCP_NOT_UDP);
11220	MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV4_EN_TCP_UDP);
11221	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV4_SIP0, 4);
11222	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV4_DIP0, 4);
11223}
11224
11225static void
11226mlxsw_sp_mp_hash_inner_custom(struct mlxsw_sp_mp_hash_config *config,
11227			      u32 hash_fields)
11228{
11229	unsigned long *inner_headers = config->inner_headers;
11230	unsigned long *inner_fields = config->inner_fields;
11231
11232	/* IPv4 Inner */
11233	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV4_EN_NOT_TCP_NOT_UDP);
11234	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV4_EN_TCP_UDP);
11235	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_SRC_IP)
11236		MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV4_SIP0, 4);
11237	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_DST_IP)
11238		MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV4_DIP0, 4);
11239	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_IP_PROTO)
11240		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV4_PROTOCOL);
11241	/* IPv6 inner */
11242	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV6_EN_NOT_TCP_NOT_UDP);
11243	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV6_EN_TCP_UDP);
11244	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_SRC_IP) {
11245		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_SIP0_7);
11246		MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV6_SIP8, 8);
11247	}
11248	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_DST_IP) {
11249		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_DIP0_7);
11250		MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV6_DIP8, 8);
11251	}
11252	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_IP_PROTO)
11253		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_NEXT_HEADER);
11254	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_FLOWLABEL)
11255		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_FLOW_LABEL);
11256	/* L4 inner */
11257	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, TCP_UDP_EN_IPV4);
11258	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, TCP_UDP_EN_IPV6);
11259	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_SRC_PORT)
11260		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_TCP_UDP_SPORT);
11261	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_DST_PORT)
11262		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_TCP_UDP_DPORT);
11263}
11264
11265static void mlxsw_sp_mp4_hash_init(struct mlxsw_sp *mlxsw_sp,
11266				   struct mlxsw_sp_mp_hash_config *config)
11267{
11268	struct net *net = mlxsw_sp_net(mlxsw_sp);
11269	unsigned long *headers = config->headers;
11270	unsigned long *fields = config->fields;
11271	u32 hash_fields;
11272
11273	switch (READ_ONCE(net->ipv4.sysctl_fib_multipath_hash_policy)) {
11274	case 0:
11275		mlxsw_sp_mp4_hash_outer_addr(config);
11276		break;
11277	case 1:
11278		mlxsw_sp_mp4_hash_outer_addr(config);
11279		MLXSW_SP_MP_HASH_HEADER_SET(headers, TCP_UDP_EN_IPV4);
11280		MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV4_PROTOCOL);
11281		MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_SPORT);
11282		MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_DPORT);
11283		break;
11284	case 2:
11285		/* Outer */
11286		mlxsw_sp_mp4_hash_outer_addr(config);
11287		/* Inner */
11288		mlxsw_sp_mp_hash_inner_l3(config);
11289		break;
11290	case 3:
11291		hash_fields = READ_ONCE(net->ipv4.sysctl_fib_multipath_hash_fields);
11292		/* Outer */
11293		MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV4_EN_NOT_TCP_NOT_UDP);
11294		MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV4_EN_TCP_UDP);
11295		MLXSW_SP_MP_HASH_HEADER_SET(headers, TCP_UDP_EN_IPV4);
11296		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_IP)
11297			MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV4_SIP0, 4);
11298		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_IP)
11299			MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV4_DIP0, 4);
11300		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_IP_PROTO)
11301			MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV4_PROTOCOL);
11302		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_PORT)
11303			MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_SPORT);
11304		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_PORT)
11305			MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_DPORT);
11306		/* Inner */
11307		mlxsw_sp_mp_hash_inner_custom(config, hash_fields);
11308		break;
11309	}
11310}
11311
11312static void mlxsw_sp_mp6_hash_outer_addr(struct mlxsw_sp_mp_hash_config *config)
11313{
11314	unsigned long *headers = config->headers;
11315	unsigned long *fields = config->fields;
11316
11317	MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV6_EN_NOT_TCP_NOT_UDP);
11318	MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV6_EN_TCP_UDP);
11319	MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_SIP0_7);
11320	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV6_SIP8, 8);
11321	MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_DIP0_7);
11322	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV6_DIP8, 8);
11323}
11324
11325static void mlxsw_sp_mp6_hash_init(struct mlxsw_sp *mlxsw_sp,
11326				   struct mlxsw_sp_mp_hash_config *config)
11327{
11328	u32 hash_fields = ip6_multipath_hash_fields(mlxsw_sp_net(mlxsw_sp));
11329	unsigned long *headers = config->headers;
11330	unsigned long *fields = config->fields;
11331
11332	switch (ip6_multipath_hash_policy(mlxsw_sp_net(mlxsw_sp))) {
11333	case 0:
11334		mlxsw_sp_mp6_hash_outer_addr(config);
11335		MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_NEXT_HEADER);
11336		MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_FLOW_LABEL);
11337		break;
11338	case 1:
11339		mlxsw_sp_mp6_hash_outer_addr(config);
11340		MLXSW_SP_MP_HASH_HEADER_SET(headers, TCP_UDP_EN_IPV6);
11341		MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_NEXT_HEADER);
11342		MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_SPORT);
11343		MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_DPORT);
11344		break;
11345	case 2:
11346		/* Outer */
11347		mlxsw_sp_mp6_hash_outer_addr(config);
11348		MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_NEXT_HEADER);
11349		MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_FLOW_LABEL);
11350		/* Inner */
11351		mlxsw_sp_mp_hash_inner_l3(config);
11352		config->inc_parsing_depth = true;
11353		break;
11354	case 3:
11355		/* Outer */
11356		MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV6_EN_NOT_TCP_NOT_UDP);
11357		MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV6_EN_TCP_UDP);
11358		MLXSW_SP_MP_HASH_HEADER_SET(headers, TCP_UDP_EN_IPV6);
11359		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_IP) {
11360			MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_SIP0_7);
11361			MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV6_SIP8, 8);
11362		}
11363		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_IP) {
11364			MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_DIP0_7);
11365			MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV6_DIP8, 8);
11366		}
11367		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_IP_PROTO)
11368			MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_NEXT_HEADER);
11369		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_FLOWLABEL)
11370			MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_FLOW_LABEL);
11371		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_PORT)
11372			MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_SPORT);
11373		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_PORT)
11374			MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_DPORT);
11375		/* Inner */
11376		mlxsw_sp_mp_hash_inner_custom(config, hash_fields);
11377		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_MASK)
11378			config->inc_parsing_depth = true;
11379		break;
11380	}
11381}
11382
11383static int mlxsw_sp_mp_hash_parsing_depth_adjust(struct mlxsw_sp *mlxsw_sp,
11384						 bool old_inc_parsing_depth,
11385						 bool new_inc_parsing_depth)
11386{
11387	int err;
11388
11389	if (!old_inc_parsing_depth && new_inc_parsing_depth) {
11390		err = mlxsw_sp_parsing_depth_inc(mlxsw_sp);
11391		if (err)
11392			return err;
11393		mlxsw_sp->router->inc_parsing_depth = true;
11394	} else if (old_inc_parsing_depth && !new_inc_parsing_depth) {
11395		mlxsw_sp_parsing_depth_dec(mlxsw_sp);
11396		mlxsw_sp->router->inc_parsing_depth = false;
11397	}
11398
11399	return 0;
11400}
11401
11402static int mlxsw_sp_mp_hash_init(struct mlxsw_sp *mlxsw_sp)
11403{
11404	bool old_inc_parsing_depth, new_inc_parsing_depth;
11405	struct mlxsw_sp_mp_hash_config config = {};
11406	struct net *net = mlxsw_sp_net(mlxsw_sp);
11407	char recr2_pl[MLXSW_REG_RECR2_LEN];
11408	unsigned long bit;
11409	u32 seed;
11410	int err;
11411
11412	seed = READ_ONCE(net->ipv4.sysctl_fib_multipath_hash_seed).user_seed;
11413	if (!seed)
11414		seed = jhash(mlxsw_sp->base_mac, sizeof(mlxsw_sp->base_mac), 0);
11415
11416	mlxsw_reg_recr2_pack(recr2_pl, seed);
11417	mlxsw_sp_mp4_hash_init(mlxsw_sp, &config);
11418	mlxsw_sp_mp6_hash_init(mlxsw_sp, &config);
11419
11420	old_inc_parsing_depth = mlxsw_sp->router->inc_parsing_depth;
11421	new_inc_parsing_depth = config.inc_parsing_depth;
11422	err = mlxsw_sp_mp_hash_parsing_depth_adjust(mlxsw_sp,
11423						    old_inc_parsing_depth,
11424						    new_inc_parsing_depth);
11425	if (err)
11426		return err;
11427
11428	for_each_set_bit(bit, config.headers, __MLXSW_REG_RECR2_HEADER_CNT)
11429		mlxsw_reg_recr2_outer_header_enables_set(recr2_pl, bit, 1);
11430	for_each_set_bit(bit, config.fields, __MLXSW_REG_RECR2_FIELD_CNT)
11431		mlxsw_reg_recr2_outer_header_fields_enable_set(recr2_pl, bit, 1);
11432	for_each_set_bit(bit, config.inner_headers, __MLXSW_REG_RECR2_HEADER_CNT)
11433		mlxsw_reg_recr2_inner_header_enables_set(recr2_pl, bit, 1);
11434	for_each_set_bit(bit, config.inner_fields, __MLXSW_REG_RECR2_INNER_FIELD_CNT)
11435		mlxsw_reg_recr2_inner_header_fields_enable_set(recr2_pl, bit, 1);
11436
11437	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(recr2), recr2_pl);
11438	if (err)
11439		goto err_reg_write;
11440
11441	return 0;
11442
11443err_reg_write:
11444	mlxsw_sp_mp_hash_parsing_depth_adjust(mlxsw_sp, new_inc_parsing_depth,
11445					      old_inc_parsing_depth);
11446	return err;
11447}
11448
11449static void mlxsw_sp_mp_hash_fini(struct mlxsw_sp *mlxsw_sp)
11450{
11451	bool old_inc_parsing_depth = mlxsw_sp->router->inc_parsing_depth;
11452
11453	mlxsw_sp_mp_hash_parsing_depth_adjust(mlxsw_sp, old_inc_parsing_depth,
11454					      false);
11455}
11456#else
11457static int mlxsw_sp_mp_hash_init(struct mlxsw_sp *mlxsw_sp)
11458{
11459	return 0;
11460}
11461
11462static void mlxsw_sp_mp_hash_fini(struct mlxsw_sp *mlxsw_sp)
11463{
11464}
11465#endif
11466
11467static int mlxsw_sp_dscp_init(struct mlxsw_sp *mlxsw_sp)
11468{
11469	char rdpm_pl[MLXSW_REG_RDPM_LEN];
11470	unsigned int i;
11471
11472	MLXSW_REG_ZERO(rdpm, rdpm_pl);
11473
11474	/* HW is determining switch priority based on DSCP-bits, but the
11475	 * kernel is still doing that based on the ToS. Since there's a
11476	 * mismatch in bits we need to make sure to translate the right
11477	 * value ToS would observe, skipping the 2 least-significant ECN bits.
11478	 */
11479	for (i = 0; i < MLXSW_REG_RDPM_DSCP_ENTRY_REC_MAX_COUNT; i++)
11480		mlxsw_reg_rdpm_pack(rdpm_pl, i, rt_tos2priority(i << 2));
11481
11482	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rdpm), rdpm_pl);
11483}
11484
11485static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
11486{
11487	struct net *net = mlxsw_sp_net(mlxsw_sp);
11488	char rgcr_pl[MLXSW_REG_RGCR_LEN];
11489	u64 max_rifs;
11490	bool usp;
11491
11492	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_RIFS))
11493		return -EIO;
11494	max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
11495	usp = READ_ONCE(net->ipv4.sysctl_ip_fwd_update_priority);
11496
11497	mlxsw_reg_rgcr_pack(rgcr_pl, true, true);
11498	mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, max_rifs);
11499	mlxsw_reg_rgcr_usp_set(rgcr_pl, usp);
11500	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
11501}
11502
11503static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
11504{
11505	char rgcr_pl[MLXSW_REG_RGCR_LEN];
11506
11507	mlxsw_reg_rgcr_pack(rgcr_pl, false, false);
11508	mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
11509}
11510
11511static int mlxsw_sp_lb_rif_init(struct mlxsw_sp *mlxsw_sp,
11512				struct netlink_ext_ack *extack)
11513{
11514	struct mlxsw_sp_router *router = mlxsw_sp->router;
11515	struct mlxsw_sp_rif *lb_rif;
11516	int err;
11517
11518	router->lb_crif = mlxsw_sp_crif_alloc(NULL);
11519	if (!router->lb_crif)
11520		return -ENOMEM;
11521
11522	/* Create a generic loopback RIF associated with the main table
11523	 * (default VRF). Any table can be used, but the main table exists
11524	 * anyway, so we do not waste resources. Loopback RIFs are usually
11525	 * created with a NULL CRIF, but this RIF is used as a fallback RIF
11526	 * for blackhole nexthops, and nexthops expect to have a valid CRIF.
11527	 */
11528	lb_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, RT_TABLE_MAIN, router->lb_crif,
11529				     extack);
11530	if (IS_ERR(lb_rif)) {
11531		err = PTR_ERR(lb_rif);
11532		goto err_ul_rif_get;
11533	}
11534
11535	return 0;
11536
11537err_ul_rif_get:
11538	mlxsw_sp_crif_free(router->lb_crif);
11539	return err;
11540}
11541
11542static void mlxsw_sp_lb_rif_fini(struct mlxsw_sp *mlxsw_sp)
11543{
11544	mlxsw_sp_ul_rif_put(mlxsw_sp->router->lb_crif->rif);
11545	mlxsw_sp_crif_free(mlxsw_sp->router->lb_crif);
11546}
11547
11548static int mlxsw_sp1_router_init(struct mlxsw_sp *mlxsw_sp)
11549{
11550	size_t size_ranges_count = ARRAY_SIZE(mlxsw_sp1_adj_grp_size_ranges);
11551
11552	mlxsw_sp->router->rif_ops_arr = mlxsw_sp1_rif_ops_arr;
11553	mlxsw_sp->router->adj_grp_size_ranges = mlxsw_sp1_adj_grp_size_ranges;
11554	mlxsw_sp->router->adj_grp_size_ranges_count = size_ranges_count;
11555
11556	return 0;
11557}
11558
11559const struct mlxsw_sp_router_ops mlxsw_sp1_router_ops = {
11560	.init = mlxsw_sp1_router_init,
11561	.ipips_init = mlxsw_sp1_ipips_init,
11562};
11563
11564static int mlxsw_sp2_router_init(struct mlxsw_sp *mlxsw_sp)
11565{
11566	size_t size_ranges_count = ARRAY_SIZE(mlxsw_sp2_adj_grp_size_ranges);
11567
11568	mlxsw_sp->router->rif_ops_arr = mlxsw_sp2_rif_ops_arr;
11569	mlxsw_sp->router->adj_grp_size_ranges = mlxsw_sp2_adj_grp_size_ranges;
11570	mlxsw_sp->router->adj_grp_size_ranges_count = size_ranges_count;
11571
11572	return 0;
11573}
11574
11575const struct mlxsw_sp_router_ops mlxsw_sp2_router_ops = {
11576	.init = mlxsw_sp2_router_init,
11577	.ipips_init = mlxsw_sp2_ipips_init,
11578};
11579
11580int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
11581			 struct netlink_ext_ack *extack)
11582{
11583	struct mlxsw_sp_router *router;
11584	struct notifier_block *nb;
11585	int err;
11586
11587	router = kzalloc(sizeof(*mlxsw_sp->router), GFP_KERNEL);
11588	if (!router)
11589		return -ENOMEM;
11590	mutex_init(&router->lock);
11591	mlxsw_sp->router = router;
11592	router->mlxsw_sp = mlxsw_sp;
11593
11594	err = mlxsw_sp->router_ops->init(mlxsw_sp);
11595	if (err)
11596		goto err_router_ops_init;
11597
11598	INIT_LIST_HEAD(&mlxsw_sp->router->nh_res_grp_list);
11599	INIT_DELAYED_WORK(&mlxsw_sp->router->nh_grp_activity_dw,
11600			  mlxsw_sp_nh_grp_activity_work);
11601	INIT_LIST_HEAD(&mlxsw_sp->router->nexthop_neighs_list);
11602	err = __mlxsw_sp_router_init(mlxsw_sp);
11603	if (err)
11604		goto err_router_init;
11605
11606	err = mlxsw_sp->router_ops->ipips_init(mlxsw_sp);
11607	if (err)
11608		goto err_ipips_init;
11609
11610	err = rhashtable_init(&mlxsw_sp->router->crif_ht,
11611			      &mlxsw_sp_crif_ht_params);
11612	if (err)
11613		goto err_crif_ht_init;
11614
11615	err = mlxsw_sp_rifs_init(mlxsw_sp);
11616	if (err)
11617		goto err_rifs_init;
11618
11619	err = rhashtable_init(&mlxsw_sp->router->nexthop_ht,
11620			      &mlxsw_sp_nexthop_ht_params);
11621	if (err)
11622		goto err_nexthop_ht_init;
11623
11624	err = rhashtable_init(&mlxsw_sp->router->nexthop_group_ht,
11625			      &mlxsw_sp_nexthop_group_ht_params);
11626	if (err)
11627		goto err_nexthop_group_ht_init;
11628
11629	INIT_LIST_HEAD(&mlxsw_sp->router->nexthop_list);
11630	err = mlxsw_sp_lpm_init(mlxsw_sp);
11631	if (err)
11632		goto err_lpm_init;
11633
11634	err = mlxsw_sp_mr_init(mlxsw_sp, &mlxsw_sp_mr_tcam_ops);
11635	if (err)
11636		goto err_mr_init;
11637
11638	err = mlxsw_sp_vrs_init(mlxsw_sp);
11639	if (err)
11640		goto err_vrs_init;
11641
11642	err = mlxsw_sp_lb_rif_init(mlxsw_sp, extack);
11643	if (err)
11644		goto err_lb_rif_init;
11645
11646	err = mlxsw_sp_neigh_init(mlxsw_sp);
11647	if (err)
11648		goto err_neigh_init;
11649
11650	err = mlxsw_sp_mp_hash_init(mlxsw_sp);
11651	if (err)
11652		goto err_mp_hash_init;
11653
11654	err = mlxsw_sp_dscp_init(mlxsw_sp);
11655	if (err)
11656		goto err_dscp_init;
11657
11658	router->inetaddr_nb.notifier_call = mlxsw_sp_inetaddr_event;
11659	err = register_inetaddr_notifier(&router->inetaddr_nb);
11660	if (err)
11661		goto err_register_inetaddr_notifier;
11662
11663	router->inet6addr_nb.notifier_call = mlxsw_sp_inet6addr_event;
11664	err = register_inet6addr_notifier(&router->inet6addr_nb);
11665	if (err)
11666		goto err_register_inet6addr_notifier;
11667
11668	router->inetaddr_valid_nb.notifier_call = mlxsw_sp_inetaddr_valid_event;
11669	err = register_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
11670	if (err)
11671		goto err_register_inetaddr_valid_notifier;
11672
11673	nb = &router->inet6addr_valid_nb;
11674	nb->notifier_call = mlxsw_sp_inet6addr_valid_event;
11675	err = register_inet6addr_validator_notifier(nb);
11676	if (err)
11677		goto err_register_inet6addr_valid_notifier;
11678
11679	mlxsw_sp->router->netevent_nb.notifier_call =
11680		mlxsw_sp_router_netevent_event;
11681	err = register_netevent_notifier(&mlxsw_sp->router->netevent_nb);
11682	if (err)
11683		goto err_register_netevent_notifier;
11684
11685	mlxsw_sp->router->netdevice_nb.notifier_call =
11686		mlxsw_sp_router_netdevice_event;
11687	err = register_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
11688					      &mlxsw_sp->router->netdevice_nb);
11689	if (err)
11690		goto err_register_netdev_notifier;
11691
11692	mlxsw_sp->router->nexthop_nb.notifier_call =
11693		mlxsw_sp_nexthop_obj_event;
11694	err = register_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
11695					&mlxsw_sp->router->nexthop_nb,
11696					extack);
11697	if (err)
11698		goto err_register_nexthop_notifier;
11699
11700	mlxsw_sp->router->fib_nb.notifier_call = mlxsw_sp_router_fib_event;
11701	err = register_fib_notifier(mlxsw_sp_net(mlxsw_sp),
11702				    &mlxsw_sp->router->fib_nb,
11703				    mlxsw_sp_router_fib_dump_flush, extack);
11704	if (err)
11705		goto err_register_fib_notifier;
11706
11707	return 0;
11708
11709err_register_fib_notifier:
11710	unregister_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
11711				    &mlxsw_sp->router->nexthop_nb);
11712err_register_nexthop_notifier:
11713	unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
11714					  &router->netdevice_nb);
11715err_register_netdev_notifier:
11716	unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb);
11717err_register_netevent_notifier:
11718	unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb);
11719err_register_inet6addr_valid_notifier:
11720	unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
11721err_register_inetaddr_valid_notifier:
11722	unregister_inet6addr_notifier(&router->inet6addr_nb);
11723err_register_inet6addr_notifier:
11724	unregister_inetaddr_notifier(&router->inetaddr_nb);
11725err_register_inetaddr_notifier:
11726	mlxsw_core_flush_owq();
11727err_dscp_init:
11728	mlxsw_sp_mp_hash_fini(mlxsw_sp);
11729err_mp_hash_init:
11730	mlxsw_sp_neigh_fini(mlxsw_sp);
11731err_neigh_init:
11732	mlxsw_sp_lb_rif_fini(mlxsw_sp);
11733err_lb_rif_init:
11734	mlxsw_sp_vrs_fini(mlxsw_sp);
11735err_vrs_init:
11736	mlxsw_sp_mr_fini(mlxsw_sp);
11737err_mr_init:
11738	mlxsw_sp_lpm_fini(mlxsw_sp);
11739err_lpm_init:
11740	rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht);
11741err_nexthop_group_ht_init:
11742	rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
11743err_nexthop_ht_init:
11744	mlxsw_sp_rifs_fini(mlxsw_sp);
11745err_rifs_init:
11746	rhashtable_destroy(&mlxsw_sp->router->crif_ht);
11747err_crif_ht_init:
11748	mlxsw_sp_ipips_fini(mlxsw_sp);
11749err_ipips_init:
11750	__mlxsw_sp_router_fini(mlxsw_sp);
11751err_router_init:
11752	cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw);
11753err_router_ops_init:
11754	mutex_destroy(&mlxsw_sp->router->lock);
11755	kfree(mlxsw_sp->router);
11756	return err;
11757}
11758
11759void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
11760{
11761	struct mlxsw_sp_router *router = mlxsw_sp->router;
11762
11763	unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp), &router->fib_nb);
11764	unregister_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
11765				    &router->nexthop_nb);
11766	unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
11767					  &router->netdevice_nb);
11768	unregister_netevent_notifier(&router->netevent_nb);
11769	unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb);
11770	unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
11771	unregister_inet6addr_notifier(&router->inet6addr_nb);
11772	unregister_inetaddr_notifier(&router->inetaddr_nb);
11773	mlxsw_core_flush_owq();
11774	mlxsw_sp_mp_hash_fini(mlxsw_sp);
11775	mlxsw_sp_neigh_fini(mlxsw_sp);
11776	mlxsw_sp_lb_rif_fini(mlxsw_sp);
11777	mlxsw_sp_vrs_fini(mlxsw_sp);
11778	mlxsw_sp_mr_fini(mlxsw_sp);
11779	mlxsw_sp_lpm_fini(mlxsw_sp);
11780	rhashtable_destroy(&router->nexthop_group_ht);
11781	rhashtable_destroy(&router->nexthop_ht);
11782	mlxsw_sp_rifs_fini(mlxsw_sp);
11783	rhashtable_destroy(&mlxsw_sp->router->crif_ht);
11784	mlxsw_sp_ipips_fini(mlxsw_sp);
11785	__mlxsw_sp_router_fini(mlxsw_sp);
11786	cancel_delayed_work_sync(&router->nh_grp_activity_dw);
11787	mutex_destroy(&router->lock);
11788	kfree(router);
11789}
~/ Read-only file preview.