xref: /openbmc/linux/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
19948a064SJiri Pirko // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
29948a064SJiri Pirko /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
3230ead01SArkadi Sharshevsky 
4230ead01SArkadi Sharshevsky #include <linux/kernel.h>
56a5c69cdSIdo Schimmel #include <linux/mutex.h>
6230ead01SArkadi Sharshevsky #include <net/devlink.h>
7230ead01SArkadi Sharshevsky 
8230ead01SArkadi Sharshevsky #include "spectrum.h"
9230ead01SArkadi Sharshevsky #include "spectrum_dpipe.h"
102ba5999fSArkadi Sharshevsky #include "spectrum_router.h"
11230ead01SArkadi Sharshevsky 
12d54b70feSArkadi Sharshevsky enum mlxsw_sp_field_metadata_id {
13d54b70feSArkadi Sharshevsky 	MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT,
14d54b70feSArkadi Sharshevsky 	MLXSW_SP_DPIPE_FIELD_METADATA_L3_FORWARD,
15d54b70feSArkadi Sharshevsky 	MLXSW_SP_DPIPE_FIELD_METADATA_L3_DROP,
16c0859d69SArkadi Sharshevsky 	MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_INDEX,
17e69cd9d7SIdo Schimmel 	MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_SIZE,
18c0859d69SArkadi Sharshevsky 	MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_HASH_INDEX,
19d54b70feSArkadi Sharshevsky };
20d54b70feSArkadi Sharshevsky 
21d54b70feSArkadi Sharshevsky static struct devlink_dpipe_field mlxsw_sp_dpipe_fields_metadata[] = {
22be2336ebSArkadi Sharshevsky 	{
23be2336ebSArkadi Sharshevsky 		.name = "erif_port",
24d54b70feSArkadi Sharshevsky 		.id = MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT,
25d54b70feSArkadi Sharshevsky 		.bitwidth = 32,
26d54b70feSArkadi Sharshevsky 		.mapping_type = DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX,
27d54b70feSArkadi Sharshevsky 	},
28be2336ebSArkadi Sharshevsky 	{
29be2336ebSArkadi Sharshevsky 		.name = "l3_forward",
30d54b70feSArkadi Sharshevsky 		.id = MLXSW_SP_DPIPE_FIELD_METADATA_L3_FORWARD,
31d54b70feSArkadi Sharshevsky 		.bitwidth = 1,
32d54b70feSArkadi Sharshevsky 	},
33be2336ebSArkadi Sharshevsky 	{
34be2336ebSArkadi Sharshevsky 		.name = "l3_drop",
35d54b70feSArkadi Sharshevsky 		.id = MLXSW_SP_DPIPE_FIELD_METADATA_L3_DROP,
36d54b70feSArkadi Sharshevsky 		.bitwidth = 1,
37d54b70feSArkadi Sharshevsky 	},
38c0859d69SArkadi Sharshevsky 	{
39c0859d69SArkadi Sharshevsky 		.name = "adj_index",
40c0859d69SArkadi Sharshevsky 		.id = MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_INDEX,
41c0859d69SArkadi Sharshevsky 		.bitwidth = 32,
42c0859d69SArkadi Sharshevsky 	},
43c0859d69SArkadi Sharshevsky 	{
44e69cd9d7SIdo Schimmel 		.name = "adj_size",
45e69cd9d7SIdo Schimmel 		.id = MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_SIZE,
46e69cd9d7SIdo Schimmel 		.bitwidth = 32,
47e69cd9d7SIdo Schimmel 	},
48e69cd9d7SIdo Schimmel 	{
49c0859d69SArkadi Sharshevsky 		.name = "adj_hash_index",
50c0859d69SArkadi Sharshevsky 		.id = MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_HASH_INDEX,
51c0859d69SArkadi Sharshevsky 		.bitwidth = 32,
52c0859d69SArkadi Sharshevsky 	},
53d54b70feSArkadi Sharshevsky };
54d54b70feSArkadi Sharshevsky 
55d54b70feSArkadi Sharshevsky enum mlxsw_sp_dpipe_header_id {
56d54b70feSArkadi Sharshevsky 	MLXSW_SP_DPIPE_HEADER_METADATA,
57d54b70feSArkadi Sharshevsky };
58d54b70feSArkadi Sharshevsky 
59d54b70feSArkadi Sharshevsky static struct devlink_dpipe_header mlxsw_sp_dpipe_header_metadata = {
60d54b70feSArkadi Sharshevsky 	.name = "mlxsw_meta",
61d54b70feSArkadi Sharshevsky 	.id = MLXSW_SP_DPIPE_HEADER_METADATA,
62d54b70feSArkadi Sharshevsky 	.fields = mlxsw_sp_dpipe_fields_metadata,
63d54b70feSArkadi Sharshevsky 	.fields_count = ARRAY_SIZE(mlxsw_sp_dpipe_fields_metadata),
64d54b70feSArkadi Sharshevsky };
65d54b70feSArkadi Sharshevsky 
66d54b70feSArkadi Sharshevsky static struct devlink_dpipe_header *mlxsw_dpipe_headers[] = {
67d54b70feSArkadi Sharshevsky 	&mlxsw_sp_dpipe_header_metadata,
686aecb36bSArkadi Sharshevsky 	&devlink_dpipe_header_ethernet,
696aecb36bSArkadi Sharshevsky 	&devlink_dpipe_header_ipv4,
70506f7dd5SArkadi Sharshevsky 	&devlink_dpipe_header_ipv6,
71d54b70feSArkadi Sharshevsky };
72230ead01SArkadi Sharshevsky 
73230ead01SArkadi Sharshevsky static struct devlink_dpipe_headers mlxsw_sp_dpipe_headers = {
74230ead01SArkadi Sharshevsky 	.headers = mlxsw_dpipe_headers,
75230ead01SArkadi Sharshevsky 	.headers_count = ARRAY_SIZE(mlxsw_dpipe_headers),
76230ead01SArkadi Sharshevsky };
77230ead01SArkadi Sharshevsky 
mlxsw_sp_dpipe_table_erif_actions_dump(void * priv,struct sk_buff * skb)78d54b70feSArkadi Sharshevsky static int mlxsw_sp_dpipe_table_erif_actions_dump(void *priv,
79d54b70feSArkadi Sharshevsky 						  struct sk_buff *skb)
80d54b70feSArkadi Sharshevsky {
81d54b70feSArkadi Sharshevsky 	struct devlink_dpipe_action action = {0};
82d54b70feSArkadi Sharshevsky 	int err;
83d54b70feSArkadi Sharshevsky 
84d54b70feSArkadi Sharshevsky 	action.type = DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY;
85d54b70feSArkadi Sharshevsky 	action.header = &mlxsw_sp_dpipe_header_metadata;
86d54b70feSArkadi Sharshevsky 	action.field_id = MLXSW_SP_DPIPE_FIELD_METADATA_L3_FORWARD;
87d54b70feSArkadi Sharshevsky 
88d54b70feSArkadi Sharshevsky 	err = devlink_dpipe_action_put(skb, &action);
89d54b70feSArkadi Sharshevsky 	if (err)
90d54b70feSArkadi Sharshevsky 		return err;
91d54b70feSArkadi Sharshevsky 
92d54b70feSArkadi Sharshevsky 	action.type = DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY;
93d54b70feSArkadi Sharshevsky 	action.header = &mlxsw_sp_dpipe_header_metadata;
94d54b70feSArkadi Sharshevsky 	action.field_id = MLXSW_SP_DPIPE_FIELD_METADATA_L3_DROP;
95d54b70feSArkadi Sharshevsky 
96d54b70feSArkadi Sharshevsky 	return devlink_dpipe_action_put(skb, &action);
97d54b70feSArkadi Sharshevsky }
98d54b70feSArkadi Sharshevsky 
mlxsw_sp_dpipe_table_erif_matches_dump(void * priv,struct sk_buff * skb)99d54b70feSArkadi Sharshevsky static int mlxsw_sp_dpipe_table_erif_matches_dump(void *priv,
100d54b70feSArkadi Sharshevsky 						  struct sk_buff *skb)
101d54b70feSArkadi Sharshevsky {
102d54b70feSArkadi Sharshevsky 	struct devlink_dpipe_match match = {0};
103d54b70feSArkadi Sharshevsky 
104d54b70feSArkadi Sharshevsky 	match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
105d54b70feSArkadi Sharshevsky 	match.header = &mlxsw_sp_dpipe_header_metadata;
106d54b70feSArkadi Sharshevsky 	match.field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT;
107d54b70feSArkadi Sharshevsky 
108d54b70feSArkadi Sharshevsky 	return devlink_dpipe_match_put(skb, &match);
109d54b70feSArkadi Sharshevsky }
110d54b70feSArkadi Sharshevsky 
1112ba5999fSArkadi Sharshevsky static void
mlxsw_sp_erif_match_action_prepare(struct devlink_dpipe_match * match,struct devlink_dpipe_action * action)1122ba5999fSArkadi Sharshevsky mlxsw_sp_erif_match_action_prepare(struct devlink_dpipe_match *match,
1132ba5999fSArkadi Sharshevsky 				   struct devlink_dpipe_action *action)
1142ba5999fSArkadi Sharshevsky {
1152ba5999fSArkadi Sharshevsky 	action->type = DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY;
1162ba5999fSArkadi Sharshevsky 	action->header = &mlxsw_sp_dpipe_header_metadata;
1172ba5999fSArkadi Sharshevsky 	action->field_id = MLXSW_SP_DPIPE_FIELD_METADATA_L3_FORWARD;
1182ba5999fSArkadi Sharshevsky 
1192ba5999fSArkadi Sharshevsky 	match->type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
1202ba5999fSArkadi Sharshevsky 	match->header = &mlxsw_sp_dpipe_header_metadata;
1212ba5999fSArkadi Sharshevsky 	match->field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT;
1222ba5999fSArkadi Sharshevsky }
1232ba5999fSArkadi Sharshevsky 
mlxsw_sp_erif_entry_prepare(struct devlink_dpipe_entry * entry,struct devlink_dpipe_value * match_value,struct devlink_dpipe_match * match,struct devlink_dpipe_value * action_value,struct devlink_dpipe_action * action)1242ba5999fSArkadi Sharshevsky static int mlxsw_sp_erif_entry_prepare(struct devlink_dpipe_entry *entry,
1252ba5999fSArkadi Sharshevsky 				       struct devlink_dpipe_value *match_value,
1262ba5999fSArkadi Sharshevsky 				       struct devlink_dpipe_match *match,
1272ba5999fSArkadi Sharshevsky 				       struct devlink_dpipe_value *action_value,
1282ba5999fSArkadi Sharshevsky 				       struct devlink_dpipe_action *action)
1292ba5999fSArkadi Sharshevsky {
1302ba5999fSArkadi Sharshevsky 	entry->match_values = match_value;
1312ba5999fSArkadi Sharshevsky 	entry->match_values_count = 1;
1322ba5999fSArkadi Sharshevsky 
1332ba5999fSArkadi Sharshevsky 	entry->action_values = action_value;
1342ba5999fSArkadi Sharshevsky 	entry->action_values_count = 1;
1352ba5999fSArkadi Sharshevsky 
1362ba5999fSArkadi Sharshevsky 	match_value->match = match;
1372ba5999fSArkadi Sharshevsky 	match_value->value_size = sizeof(u32);
1382ba5999fSArkadi Sharshevsky 	match_value->value = kmalloc(match_value->value_size, GFP_KERNEL);
1392ba5999fSArkadi Sharshevsky 	if (!match_value->value)
1402ba5999fSArkadi Sharshevsky 		return -ENOMEM;
1412ba5999fSArkadi Sharshevsky 
1422ba5999fSArkadi Sharshevsky 	action_value->action = action;
1432ba5999fSArkadi Sharshevsky 	action_value->value_size = sizeof(u32);
1442ba5999fSArkadi Sharshevsky 	action_value->value = kmalloc(action_value->value_size, GFP_KERNEL);
1452ba5999fSArkadi Sharshevsky 	if (!action_value->value)
1462ba5999fSArkadi Sharshevsky 		goto err_action_alloc;
1472ba5999fSArkadi Sharshevsky 	return 0;
1482ba5999fSArkadi Sharshevsky 
1492ba5999fSArkadi Sharshevsky err_action_alloc:
1502ba5999fSArkadi Sharshevsky 	kfree(match_value->value);
1512ba5999fSArkadi Sharshevsky 	return -ENOMEM;
1522ba5999fSArkadi Sharshevsky }
1532ba5999fSArkadi Sharshevsky 
mlxsw_sp_erif_entry_get(struct mlxsw_sp * mlxsw_sp,struct devlink_dpipe_entry * entry,struct mlxsw_sp_rif * rif,bool counters_enabled)1542ba5999fSArkadi Sharshevsky static int mlxsw_sp_erif_entry_get(struct mlxsw_sp *mlxsw_sp,
1552ba5999fSArkadi Sharshevsky 				   struct devlink_dpipe_entry *entry,
1562ba5999fSArkadi Sharshevsky 				   struct mlxsw_sp_rif *rif,
1572ba5999fSArkadi Sharshevsky 				   bool counters_enabled)
1582ba5999fSArkadi Sharshevsky {
1592ba5999fSArkadi Sharshevsky 	u32 *action_value;
1602ba5999fSArkadi Sharshevsky 	u32 *rif_value;
1612ba5999fSArkadi Sharshevsky 	u64 cnt;
1622ba5999fSArkadi Sharshevsky 	int err;
1632ba5999fSArkadi Sharshevsky 
1642ba5999fSArkadi Sharshevsky 	/* Set Match RIF index */
1652ba5999fSArkadi Sharshevsky 	rif_value = entry->match_values->value;
1662ba5999fSArkadi Sharshevsky 	*rif_value = mlxsw_sp_rif_index(rif);
1672ba5999fSArkadi Sharshevsky 	entry->match_values->mapping_value = mlxsw_sp_rif_dev_ifindex(rif);
1682ba5999fSArkadi Sharshevsky 	entry->match_values->mapping_valid = true;
1692ba5999fSArkadi Sharshevsky 
1702ba5999fSArkadi Sharshevsky 	/* Set Action Forwarding */
1712ba5999fSArkadi Sharshevsky 	action_value = entry->action_values->value;
1722ba5999fSArkadi Sharshevsky 	*action_value = 1;
1732ba5999fSArkadi Sharshevsky 
1742ba5999fSArkadi Sharshevsky 	entry->counter_valid = false;
1752ba5999fSArkadi Sharshevsky 	entry->counter = 0;
1766dd4aba3SArkadi Sharshevsky 	entry->index = mlxsw_sp_rif_index(rif);
1776dd4aba3SArkadi Sharshevsky 
1782ba5999fSArkadi Sharshevsky 	if (!counters_enabled)
1792ba5999fSArkadi Sharshevsky 		return 0;
1802ba5999fSArkadi Sharshevsky 
1812ba5999fSArkadi Sharshevsky 	err = mlxsw_sp_rif_counter_value_get(mlxsw_sp, rif,
1822ba5999fSArkadi Sharshevsky 					     MLXSW_SP_RIF_COUNTER_EGRESS,
1832ba5999fSArkadi Sharshevsky 					     &cnt);
1842ba5999fSArkadi Sharshevsky 	if (!err) {
1852ba5999fSArkadi Sharshevsky 		entry->counter = cnt;
1862ba5999fSArkadi Sharshevsky 		entry->counter_valid = true;
1872ba5999fSArkadi Sharshevsky 	}
1882ba5999fSArkadi Sharshevsky 	return 0;
1892ba5999fSArkadi Sharshevsky }
1902ba5999fSArkadi Sharshevsky 
1912ba5999fSArkadi Sharshevsky static int
mlxsw_sp_dpipe_table_erif_entries_dump(void * priv,bool counters_enabled,struct devlink_dpipe_dump_ctx * dump_ctx)19223ca5ec3SArkadi Sharshevsky mlxsw_sp_dpipe_table_erif_entries_dump(void *priv, bool counters_enabled,
1932ba5999fSArkadi Sharshevsky 				       struct devlink_dpipe_dump_ctx *dump_ctx)
1942ba5999fSArkadi Sharshevsky {
195d5d6add0SArkadi Sharshevsky 	struct devlink_dpipe_value match_value, action_value;
1962ba5999fSArkadi Sharshevsky 	struct devlink_dpipe_action action = {0};
1972ba5999fSArkadi Sharshevsky 	struct devlink_dpipe_match match = {0};
1982ba5999fSArkadi Sharshevsky 	struct devlink_dpipe_entry entry = {0};
1992ba5999fSArkadi Sharshevsky 	struct mlxsw_sp *mlxsw_sp = priv;
2002ba5999fSArkadi Sharshevsky 	unsigned int rif_count;
2012ba5999fSArkadi Sharshevsky 	int i, j;
2022ba5999fSArkadi Sharshevsky 	int err;
2032ba5999fSArkadi Sharshevsky 
204d5d6add0SArkadi Sharshevsky 	memset(&match_value, 0, sizeof(match_value));
205d5d6add0SArkadi Sharshevsky 	memset(&action_value, 0, sizeof(action_value));
206d5d6add0SArkadi Sharshevsky 
2072ba5999fSArkadi Sharshevsky 	mlxsw_sp_erif_match_action_prepare(&match, &action);
2082ba5999fSArkadi Sharshevsky 	err = mlxsw_sp_erif_entry_prepare(&entry, &match_value, &match,
2092ba5999fSArkadi Sharshevsky 					  &action_value, &action);
2102ba5999fSArkadi Sharshevsky 	if (err)
2112ba5999fSArkadi Sharshevsky 		return err;
2122ba5999fSArkadi Sharshevsky 
2132ba5999fSArkadi Sharshevsky 	rif_count = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
2146a5c69cdSIdo Schimmel 	mutex_lock(&mlxsw_sp->router->lock);
2152ba5999fSArkadi Sharshevsky 	i = 0;
2162ba5999fSArkadi Sharshevsky start_again:
2172ba5999fSArkadi Sharshevsky 	err = devlink_dpipe_entry_ctx_prepare(dump_ctx);
2182ba5999fSArkadi Sharshevsky 	if (err)
2193a99cbb6SIdo Schimmel 		goto err_ctx_prepare;
2202ba5999fSArkadi Sharshevsky 	j = 0;
2212ba5999fSArkadi Sharshevsky 	for (; i < rif_count; i++) {
2225f9efffbSIdo Schimmel 		struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
2235f9efffbSIdo Schimmel 
224*0255f748SPetr Machata 		if (!rif || !mlxsw_sp_rif_has_dev(rif))
2252ba5999fSArkadi Sharshevsky 			continue;
2265f9efffbSIdo Schimmel 		err = mlxsw_sp_erif_entry_get(mlxsw_sp, &entry, rif,
2272ba5999fSArkadi Sharshevsky 					      counters_enabled);
2282ba5999fSArkadi Sharshevsky 		if (err)
2292ba5999fSArkadi Sharshevsky 			goto err_entry_get;
2302ba5999fSArkadi Sharshevsky 		err = devlink_dpipe_entry_ctx_append(dump_ctx, &entry);
2312ba5999fSArkadi Sharshevsky 		if (err) {
2322ba5999fSArkadi Sharshevsky 			if (err == -EMSGSIZE) {
2332ba5999fSArkadi Sharshevsky 				if (!j)
2342ba5999fSArkadi Sharshevsky 					goto err_entry_append;
2352ba5999fSArkadi Sharshevsky 				break;
2362ba5999fSArkadi Sharshevsky 			}
2372ba5999fSArkadi Sharshevsky 			goto err_entry_append;
2382ba5999fSArkadi Sharshevsky 		}
2392ba5999fSArkadi Sharshevsky 		j++;
2402ba5999fSArkadi Sharshevsky 	}
2412ba5999fSArkadi Sharshevsky 
2422ba5999fSArkadi Sharshevsky 	devlink_dpipe_entry_ctx_close(dump_ctx);
2432ba5999fSArkadi Sharshevsky 	if (i != rif_count)
2442ba5999fSArkadi Sharshevsky 		goto start_again;
2456a5c69cdSIdo Schimmel 	mutex_unlock(&mlxsw_sp->router->lock);
2462ba5999fSArkadi Sharshevsky 
24735807324SArkadi Sharshevsky 	devlink_dpipe_entry_clear(&entry);
2482ba5999fSArkadi Sharshevsky 	return 0;
2492ba5999fSArkadi Sharshevsky err_entry_append:
2502ba5999fSArkadi Sharshevsky err_entry_get:
2513a99cbb6SIdo Schimmel err_ctx_prepare:
2526a5c69cdSIdo Schimmel 	mutex_unlock(&mlxsw_sp->router->lock);
25335807324SArkadi Sharshevsky 	devlink_dpipe_entry_clear(&entry);
2542ba5999fSArkadi Sharshevsky 	return err;
2552ba5999fSArkadi Sharshevsky }
2562ba5999fSArkadi Sharshevsky 
mlxsw_sp_dpipe_table_erif_counters_update(void * priv,bool enable)25723ca5ec3SArkadi Sharshevsky static int mlxsw_sp_dpipe_table_erif_counters_update(void *priv, bool enable)
2582ba5999fSArkadi Sharshevsky {
2592ba5999fSArkadi Sharshevsky 	struct mlxsw_sp *mlxsw_sp = priv;
2602ba5999fSArkadi Sharshevsky 	int i;
2612ba5999fSArkadi Sharshevsky 
2626a5c69cdSIdo Schimmel 	mutex_lock(&mlxsw_sp->router->lock);
2632ba5999fSArkadi Sharshevsky 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
2645f9efffbSIdo Schimmel 		struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
2655f9efffbSIdo Schimmel 
2665f9efffbSIdo Schimmel 		if (!rif)
2672ba5999fSArkadi Sharshevsky 			continue;
2682ba5999fSArkadi Sharshevsky 		if (enable)
2699834e246SPetr Machata 			mlxsw_sp_rif_counter_alloc(rif,
2702ba5999fSArkadi Sharshevsky 						   MLXSW_SP_RIF_COUNTER_EGRESS);
2712ba5999fSArkadi Sharshevsky 		else
2729834e246SPetr Machata 			mlxsw_sp_rif_counter_free(rif,
2732ba5999fSArkadi Sharshevsky 						  MLXSW_SP_RIF_COUNTER_EGRESS);
2742ba5999fSArkadi Sharshevsky 	}
2756a5c69cdSIdo Schimmel 	mutex_unlock(&mlxsw_sp->router->lock);
2762ba5999fSArkadi Sharshevsky 	return 0;
2772ba5999fSArkadi Sharshevsky }
2782ba5999fSArkadi Sharshevsky 
mlxsw_sp_dpipe_table_erif_size_get(void * priv)279ffd3cdccSArkadi Sharshevsky static u64 mlxsw_sp_dpipe_table_erif_size_get(void *priv)
280ffd3cdccSArkadi Sharshevsky {
281ffd3cdccSArkadi Sharshevsky 	struct mlxsw_sp *mlxsw_sp = priv;
282ffd3cdccSArkadi Sharshevsky 
283ffd3cdccSArkadi Sharshevsky 	return MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
284ffd3cdccSArkadi Sharshevsky }
285ffd3cdccSArkadi Sharshevsky 
286d54b70feSArkadi Sharshevsky static struct devlink_dpipe_table_ops mlxsw_sp_erif_ops = {
287d54b70feSArkadi Sharshevsky 	.matches_dump = mlxsw_sp_dpipe_table_erif_matches_dump,
288d54b70feSArkadi Sharshevsky 	.actions_dump = mlxsw_sp_dpipe_table_erif_actions_dump,
28923ca5ec3SArkadi Sharshevsky 	.entries_dump = mlxsw_sp_dpipe_table_erif_entries_dump,
29023ca5ec3SArkadi Sharshevsky 	.counters_set_update = mlxsw_sp_dpipe_table_erif_counters_update,
291ffd3cdccSArkadi Sharshevsky 	.size_get = mlxsw_sp_dpipe_table_erif_size_get,
292d54b70feSArkadi Sharshevsky };
293d54b70feSArkadi Sharshevsky 
mlxsw_sp_dpipe_erif_table_init(struct mlxsw_sp * mlxsw_sp)294d54b70feSArkadi Sharshevsky static int mlxsw_sp_dpipe_erif_table_init(struct mlxsw_sp *mlxsw_sp)
295d54b70feSArkadi Sharshevsky {
296d54b70feSArkadi Sharshevsky 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
297d54b70feSArkadi Sharshevsky 
29872a4c8c9SJiri Pirko 	return devl_dpipe_table_register(devlink,
299d54b70feSArkadi Sharshevsky 					 MLXSW_SP_DPIPE_TABLE_NAME_ERIF,
300d54b70feSArkadi Sharshevsky 					 &mlxsw_sp_erif_ops,
301ffd3cdccSArkadi Sharshevsky 					 mlxsw_sp, false);
302d54b70feSArkadi Sharshevsky }
303d54b70feSArkadi Sharshevsky 
mlxsw_sp_dpipe_erif_table_fini(struct mlxsw_sp * mlxsw_sp)304d54b70feSArkadi Sharshevsky static void mlxsw_sp_dpipe_erif_table_fini(struct mlxsw_sp *mlxsw_sp)
305d54b70feSArkadi Sharshevsky {
306d54b70feSArkadi Sharshevsky 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
307d54b70feSArkadi Sharshevsky 
30872a4c8c9SJiri Pirko 	devl_dpipe_table_unregister(devlink, MLXSW_SP_DPIPE_TABLE_NAME_ERIF);
309d54b70feSArkadi Sharshevsky }
310d54b70feSArkadi Sharshevsky 
mlxsw_sp_dpipe_table_host_matches_dump(struct sk_buff * skb,int type)3116aecb36bSArkadi Sharshevsky static int mlxsw_sp_dpipe_table_host_matches_dump(struct sk_buff *skb, int type)
3126aecb36bSArkadi Sharshevsky {
3136aecb36bSArkadi Sharshevsky 	struct devlink_dpipe_match match = {0};
3146aecb36bSArkadi Sharshevsky 	int err;
3156aecb36bSArkadi Sharshevsky 
3166aecb36bSArkadi Sharshevsky 	match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
3176aecb36bSArkadi Sharshevsky 	match.header = &mlxsw_sp_dpipe_header_metadata;
3186aecb36bSArkadi Sharshevsky 	match.field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT;
3196aecb36bSArkadi Sharshevsky 
3206aecb36bSArkadi Sharshevsky 	err = devlink_dpipe_match_put(skb, &match);
3216aecb36bSArkadi Sharshevsky 	if (err)
3226aecb36bSArkadi Sharshevsky 		return err;
3236aecb36bSArkadi Sharshevsky 
324506f7dd5SArkadi Sharshevsky 	switch (type) {
325506f7dd5SArkadi Sharshevsky 	case AF_INET:
3266aecb36bSArkadi Sharshevsky 		match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
3276aecb36bSArkadi Sharshevsky 		match.header = &devlink_dpipe_header_ipv4;
3286aecb36bSArkadi Sharshevsky 		match.field_id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP;
329506f7dd5SArkadi Sharshevsky 		break;
330506f7dd5SArkadi Sharshevsky 	case AF_INET6:
331506f7dd5SArkadi Sharshevsky 		match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
332506f7dd5SArkadi Sharshevsky 		match.header = &devlink_dpipe_header_ipv6;
333506f7dd5SArkadi Sharshevsky 		match.field_id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP;
334506f7dd5SArkadi Sharshevsky 		break;
335506f7dd5SArkadi Sharshevsky 	default:
336506f7dd5SArkadi Sharshevsky 		WARN_ON(1);
337506f7dd5SArkadi Sharshevsky 		return -EINVAL;
338506f7dd5SArkadi Sharshevsky 	}
3396aecb36bSArkadi Sharshevsky 
3406aecb36bSArkadi Sharshevsky 	return devlink_dpipe_match_put(skb, &match);
3416aecb36bSArkadi Sharshevsky }
3426aecb36bSArkadi Sharshevsky 
3436aecb36bSArkadi Sharshevsky static int
mlxsw_sp_dpipe_table_host4_matches_dump(void * priv,struct sk_buff * skb)3446aecb36bSArkadi Sharshevsky mlxsw_sp_dpipe_table_host4_matches_dump(void *priv, struct sk_buff *skb)
3456aecb36bSArkadi Sharshevsky {
3466aecb36bSArkadi Sharshevsky 	return mlxsw_sp_dpipe_table_host_matches_dump(skb, AF_INET);
3476aecb36bSArkadi Sharshevsky }
3486aecb36bSArkadi Sharshevsky 
3496aecb36bSArkadi Sharshevsky static int
mlxsw_sp_dpipe_table_host_actions_dump(void * priv,struct sk_buff * skb)350506f7dd5SArkadi Sharshevsky mlxsw_sp_dpipe_table_host_actions_dump(void *priv, struct sk_buff *skb)
3516aecb36bSArkadi Sharshevsky {
3526aecb36bSArkadi Sharshevsky 	struct devlink_dpipe_action action = {0};
3536aecb36bSArkadi Sharshevsky 
3546aecb36bSArkadi Sharshevsky 	action.type = DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY;
3556aecb36bSArkadi Sharshevsky 	action.header = &devlink_dpipe_header_ethernet;
3566aecb36bSArkadi Sharshevsky 	action.field_id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC;
3576aecb36bSArkadi Sharshevsky 
3586aecb36bSArkadi Sharshevsky 	return devlink_dpipe_action_put(skb, &action);
3596aecb36bSArkadi Sharshevsky }
3606aecb36bSArkadi Sharshevsky 
361a86f0309SArkadi Sharshevsky enum mlxsw_sp_dpipe_table_host_match {
362a86f0309SArkadi Sharshevsky 	MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF,
363a86f0309SArkadi Sharshevsky 	MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP,
364a86f0309SArkadi Sharshevsky 	MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT,
365a86f0309SArkadi Sharshevsky };
366a86f0309SArkadi Sharshevsky 
367a86f0309SArkadi Sharshevsky static void
mlxsw_sp_dpipe_table_host_match_action_prepare(struct devlink_dpipe_match * matches,struct devlink_dpipe_action * action,int type)368a86f0309SArkadi Sharshevsky mlxsw_sp_dpipe_table_host_match_action_prepare(struct devlink_dpipe_match *matches,
369a86f0309SArkadi Sharshevsky 					       struct devlink_dpipe_action *action,
370a86f0309SArkadi Sharshevsky 					       int type)
371a86f0309SArkadi Sharshevsky {
372a86f0309SArkadi Sharshevsky 	struct devlink_dpipe_match *match;
373a86f0309SArkadi Sharshevsky 
374a86f0309SArkadi Sharshevsky 	match = &matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF];
375a86f0309SArkadi Sharshevsky 	match->type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
376a86f0309SArkadi Sharshevsky 	match->header = &mlxsw_sp_dpipe_header_metadata;
377a86f0309SArkadi Sharshevsky 	match->field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT;
378a86f0309SArkadi Sharshevsky 
379a86f0309SArkadi Sharshevsky 	match = &matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
380a86f0309SArkadi Sharshevsky 	match->type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
381410774bdSArkadi Sharshevsky 	switch (type) {
382410774bdSArkadi Sharshevsky 	case AF_INET:
383a86f0309SArkadi Sharshevsky 		match->header = &devlink_dpipe_header_ipv4;
384a86f0309SArkadi Sharshevsky 		match->field_id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP;
385410774bdSArkadi Sharshevsky 		break;
386410774bdSArkadi Sharshevsky 	case AF_INET6:
387410774bdSArkadi Sharshevsky 		match->header = &devlink_dpipe_header_ipv6;
388410774bdSArkadi Sharshevsky 		match->field_id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP;
389410774bdSArkadi Sharshevsky 		break;
390410774bdSArkadi Sharshevsky 	default:
391410774bdSArkadi Sharshevsky 		WARN_ON(1);
392410774bdSArkadi Sharshevsky 		return;
393410774bdSArkadi Sharshevsky 	}
394a86f0309SArkadi Sharshevsky 
395a86f0309SArkadi Sharshevsky 	action->type = DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY;
396a86f0309SArkadi Sharshevsky 	action->header = &devlink_dpipe_header_ethernet;
397a86f0309SArkadi Sharshevsky 	action->field_id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC;
398a86f0309SArkadi Sharshevsky }
399a86f0309SArkadi Sharshevsky 
400a86f0309SArkadi Sharshevsky static int
mlxsw_sp_dpipe_table_host_entry_prepare(struct devlink_dpipe_entry * entry,struct devlink_dpipe_value * match_values,struct devlink_dpipe_match * matches,struct devlink_dpipe_value * action_value,struct devlink_dpipe_action * action,int type)401a86f0309SArkadi Sharshevsky mlxsw_sp_dpipe_table_host_entry_prepare(struct devlink_dpipe_entry *entry,
402a86f0309SArkadi Sharshevsky 					struct devlink_dpipe_value *match_values,
403a86f0309SArkadi Sharshevsky 					struct devlink_dpipe_match *matches,
404a86f0309SArkadi Sharshevsky 					struct devlink_dpipe_value *action_value,
405a86f0309SArkadi Sharshevsky 					struct devlink_dpipe_action *action,
406a86f0309SArkadi Sharshevsky 					int type)
407a86f0309SArkadi Sharshevsky {
408a86f0309SArkadi Sharshevsky 	struct devlink_dpipe_value *match_value;
409a86f0309SArkadi Sharshevsky 	struct devlink_dpipe_match *match;
410a86f0309SArkadi Sharshevsky 
411a86f0309SArkadi Sharshevsky 	entry->match_values = match_values;
412a86f0309SArkadi Sharshevsky 	entry->match_values_count = MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT;
413a86f0309SArkadi Sharshevsky 
414a86f0309SArkadi Sharshevsky 	entry->action_values = action_value;
415a86f0309SArkadi Sharshevsky 	entry->action_values_count = 1;
416a86f0309SArkadi Sharshevsky 
417a86f0309SArkadi Sharshevsky 	match = &matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF];
418a86f0309SArkadi Sharshevsky 	match_value = &match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF];
419a86f0309SArkadi Sharshevsky 
420a86f0309SArkadi Sharshevsky 	match_value->match = match;
421a86f0309SArkadi Sharshevsky 	match_value->value_size = sizeof(u32);
422a86f0309SArkadi Sharshevsky 	match_value->value = kmalloc(match_value->value_size, GFP_KERNEL);
423a86f0309SArkadi Sharshevsky 	if (!match_value->value)
424a86f0309SArkadi Sharshevsky 		return -ENOMEM;
425a86f0309SArkadi Sharshevsky 
426a86f0309SArkadi Sharshevsky 	match = &matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
427a86f0309SArkadi Sharshevsky 	match_value = &match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
428a86f0309SArkadi Sharshevsky 
429a86f0309SArkadi Sharshevsky 	match_value->match = match;
430410774bdSArkadi Sharshevsky 	switch (type) {
431410774bdSArkadi Sharshevsky 	case AF_INET:
432a86f0309SArkadi Sharshevsky 		match_value->value_size = sizeof(u32);
433410774bdSArkadi Sharshevsky 		break;
434410774bdSArkadi Sharshevsky 	case AF_INET6:
435410774bdSArkadi Sharshevsky 		match_value->value_size = sizeof(struct in6_addr);
436410774bdSArkadi Sharshevsky 		break;
437410774bdSArkadi Sharshevsky 	default:
438410774bdSArkadi Sharshevsky 		WARN_ON(1);
439410774bdSArkadi Sharshevsky 		return -EINVAL;
440410774bdSArkadi Sharshevsky 	}
441410774bdSArkadi Sharshevsky 
442a86f0309SArkadi Sharshevsky 	match_value->value = kmalloc(match_value->value_size, GFP_KERNEL);
443a86f0309SArkadi Sharshevsky 	if (!match_value->value)
444a86f0309SArkadi Sharshevsky 		return -ENOMEM;
445a86f0309SArkadi Sharshevsky 
446a86f0309SArkadi Sharshevsky 	action_value->action = action;
447a86f0309SArkadi Sharshevsky 	action_value->value_size = sizeof(u64);
448a86f0309SArkadi Sharshevsky 	action_value->value = kmalloc(action_value->value_size, GFP_KERNEL);
449a86f0309SArkadi Sharshevsky 	if (!action_value->value)
450a86f0309SArkadi Sharshevsky 		return -ENOMEM;
451a86f0309SArkadi Sharshevsky 
452a86f0309SArkadi Sharshevsky 	return 0;
453a86f0309SArkadi Sharshevsky }
454a86f0309SArkadi Sharshevsky 
455a86f0309SArkadi Sharshevsky static void
__mlxsw_sp_dpipe_table_host_entry_fill(struct devlink_dpipe_entry * entry,struct mlxsw_sp_rif * rif,unsigned char * ha,void * dip)4566049e539SArkadi Sharshevsky __mlxsw_sp_dpipe_table_host_entry_fill(struct devlink_dpipe_entry *entry,
457a86f0309SArkadi Sharshevsky 				       struct mlxsw_sp_rif *rif,
4586049e539SArkadi Sharshevsky 				       unsigned char *ha, void *dip)
459a86f0309SArkadi Sharshevsky {
460a86f0309SArkadi Sharshevsky 	struct devlink_dpipe_value *value;
461a86f0309SArkadi Sharshevsky 	u32 *rif_value;
462a86f0309SArkadi Sharshevsky 	u8 *ha_value;
463a86f0309SArkadi Sharshevsky 
464a86f0309SArkadi Sharshevsky 	/* Set Match RIF index */
465a86f0309SArkadi Sharshevsky 	value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF];
466a86f0309SArkadi Sharshevsky 
467a86f0309SArkadi Sharshevsky 	rif_value = value->value;
468a86f0309SArkadi Sharshevsky 	*rif_value = mlxsw_sp_rif_index(rif);
469a86f0309SArkadi Sharshevsky 	value->mapping_value = mlxsw_sp_rif_dev_ifindex(rif);
470a86f0309SArkadi Sharshevsky 	value->mapping_valid = true;
471a86f0309SArkadi Sharshevsky 
472a86f0309SArkadi Sharshevsky 	/* Set Match DIP */
473a86f0309SArkadi Sharshevsky 	value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
4746049e539SArkadi Sharshevsky 	memcpy(value->value, dip, value->value_size);
475a86f0309SArkadi Sharshevsky 
476a86f0309SArkadi Sharshevsky 	/* Set Action DMAC */
477a86f0309SArkadi Sharshevsky 	value = entry->action_values;
478a86f0309SArkadi Sharshevsky 	ha_value = value->value;
479a86f0309SArkadi Sharshevsky 	ether_addr_copy(ha_value, ha);
480a86f0309SArkadi Sharshevsky }
481a86f0309SArkadi Sharshevsky 
482a86f0309SArkadi Sharshevsky static void
mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry * entry,struct mlxsw_sp_neigh_entry * neigh_entry,struct mlxsw_sp_rif * rif)483a86f0309SArkadi Sharshevsky mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry *entry,
484a86f0309SArkadi Sharshevsky 				      struct mlxsw_sp_neigh_entry *neigh_entry,
485a86f0309SArkadi Sharshevsky 				      struct mlxsw_sp_rif *rif)
486a86f0309SArkadi Sharshevsky {
487a86f0309SArkadi Sharshevsky 	unsigned char *ha;
488a86f0309SArkadi Sharshevsky 	u32 dip;
489a86f0309SArkadi Sharshevsky 
490a86f0309SArkadi Sharshevsky 	ha = mlxsw_sp_neigh_entry_ha(neigh_entry);
491a86f0309SArkadi Sharshevsky 	dip = mlxsw_sp_neigh4_entry_dip(neigh_entry);
4926049e539SArkadi Sharshevsky 	__mlxsw_sp_dpipe_table_host_entry_fill(entry, rif, ha, &dip);
493a86f0309SArkadi Sharshevsky }
494a86f0309SArkadi Sharshevsky 
495a86f0309SArkadi Sharshevsky static void
mlxsw_sp_dpipe_table_host6_entry_fill(struct devlink_dpipe_entry * entry,struct mlxsw_sp_neigh_entry * neigh_entry,struct mlxsw_sp_rif * rif)496410774bdSArkadi Sharshevsky mlxsw_sp_dpipe_table_host6_entry_fill(struct devlink_dpipe_entry *entry,
497410774bdSArkadi Sharshevsky 				      struct mlxsw_sp_neigh_entry *neigh_entry,
498410774bdSArkadi Sharshevsky 				      struct mlxsw_sp_rif *rif)
499410774bdSArkadi Sharshevsky {
500410774bdSArkadi Sharshevsky 	struct in6_addr *dip;
501410774bdSArkadi Sharshevsky 	unsigned char *ha;
502410774bdSArkadi Sharshevsky 
503410774bdSArkadi Sharshevsky 	ha = mlxsw_sp_neigh_entry_ha(neigh_entry);
504410774bdSArkadi Sharshevsky 	dip = mlxsw_sp_neigh6_entry_dip(neigh_entry);
505410774bdSArkadi Sharshevsky 
506410774bdSArkadi Sharshevsky 	__mlxsw_sp_dpipe_table_host_entry_fill(entry, rif, ha, dip);
507410774bdSArkadi Sharshevsky }
508410774bdSArkadi Sharshevsky 
509410774bdSArkadi Sharshevsky static void
mlxsw_sp_dpipe_table_host_entry_fill(struct mlxsw_sp * mlxsw_sp,struct devlink_dpipe_entry * entry,struct mlxsw_sp_neigh_entry * neigh_entry,struct mlxsw_sp_rif * rif,int type)510a86f0309SArkadi Sharshevsky mlxsw_sp_dpipe_table_host_entry_fill(struct mlxsw_sp *mlxsw_sp,
511a86f0309SArkadi Sharshevsky 				     struct devlink_dpipe_entry *entry,
512a86f0309SArkadi Sharshevsky 				     struct mlxsw_sp_neigh_entry *neigh_entry,
513a86f0309SArkadi Sharshevsky 				     struct mlxsw_sp_rif *rif,
514a86f0309SArkadi Sharshevsky 				     int type)
515a86f0309SArkadi Sharshevsky {
516a86f0309SArkadi Sharshevsky 	int err;
517a86f0309SArkadi Sharshevsky 
518410774bdSArkadi Sharshevsky 	switch (type) {
519410774bdSArkadi Sharshevsky 	case AF_INET:
520a86f0309SArkadi Sharshevsky 		mlxsw_sp_dpipe_table_host4_entry_fill(entry, neigh_entry, rif);
521410774bdSArkadi Sharshevsky 		break;
522410774bdSArkadi Sharshevsky 	case AF_INET6:
523410774bdSArkadi Sharshevsky 		mlxsw_sp_dpipe_table_host6_entry_fill(entry, neigh_entry, rif);
524410774bdSArkadi Sharshevsky 		break;
525410774bdSArkadi Sharshevsky 	default:
526410774bdSArkadi Sharshevsky 		WARN_ON(1);
527410774bdSArkadi Sharshevsky 		return;
528410774bdSArkadi Sharshevsky 	}
529410774bdSArkadi Sharshevsky 
530a86f0309SArkadi Sharshevsky 	err = mlxsw_sp_neigh_counter_get(mlxsw_sp, neigh_entry,
531a86f0309SArkadi Sharshevsky 					 &entry->counter);
532a86f0309SArkadi Sharshevsky 	if (!err)
533a86f0309SArkadi Sharshevsky 		entry->counter_valid = true;
534a86f0309SArkadi Sharshevsky }
535a86f0309SArkadi Sharshevsky 
536a86f0309SArkadi Sharshevsky static int
mlxsw_sp_dpipe_table_host_entries_get(struct mlxsw_sp * mlxsw_sp,struct devlink_dpipe_entry * entry,bool counters_enabled,struct devlink_dpipe_dump_ctx * dump_ctx,int type)537a86f0309SArkadi Sharshevsky mlxsw_sp_dpipe_table_host_entries_get(struct mlxsw_sp *mlxsw_sp,
538a86f0309SArkadi Sharshevsky 				      struct devlink_dpipe_entry *entry,
539a86f0309SArkadi Sharshevsky 				      bool counters_enabled,
540a86f0309SArkadi Sharshevsky 				      struct devlink_dpipe_dump_ctx *dump_ctx,
541a86f0309SArkadi Sharshevsky 				      int type)
542a86f0309SArkadi Sharshevsky {
543a86f0309SArkadi Sharshevsky 	int rif_neigh_count = 0;
544a86f0309SArkadi Sharshevsky 	int rif_neigh_skip = 0;
545a86f0309SArkadi Sharshevsky 	int neigh_count = 0;
546a86f0309SArkadi Sharshevsky 	int rif_count;
547a86f0309SArkadi Sharshevsky 	int i, j;
548a86f0309SArkadi Sharshevsky 	int err;
549a86f0309SArkadi Sharshevsky 
5506a5c69cdSIdo Schimmel 	mutex_lock(&mlxsw_sp->router->lock);
551a86f0309SArkadi Sharshevsky 	i = 0;
552a86f0309SArkadi Sharshevsky 	rif_count = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
553a86f0309SArkadi Sharshevsky start_again:
554a86f0309SArkadi Sharshevsky 	err = devlink_dpipe_entry_ctx_prepare(dump_ctx);
555a86f0309SArkadi Sharshevsky 	if (err)
556a86f0309SArkadi Sharshevsky 		goto err_ctx_prepare;
557a86f0309SArkadi Sharshevsky 	j = 0;
558a86f0309SArkadi Sharshevsky 	rif_neigh_skip = rif_neigh_count;
559a86f0309SArkadi Sharshevsky 	for (; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
560a86f0309SArkadi Sharshevsky 		struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
561a86f0309SArkadi Sharshevsky 		struct mlxsw_sp_neigh_entry *neigh_entry;
562a86f0309SArkadi Sharshevsky 
563a86f0309SArkadi Sharshevsky 		if (!rif)
564a86f0309SArkadi Sharshevsky 			continue;
565a86f0309SArkadi Sharshevsky 
566a86f0309SArkadi Sharshevsky 		rif_neigh_count = 0;
567a86f0309SArkadi Sharshevsky 		mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {
568410774bdSArkadi Sharshevsky 			int neigh_type = mlxsw_sp_neigh_entry_type(neigh_entry);
569410774bdSArkadi Sharshevsky 
570410774bdSArkadi Sharshevsky 			if (neigh_type != type)
571410774bdSArkadi Sharshevsky 				continue;
572410774bdSArkadi Sharshevsky 
573410774bdSArkadi Sharshevsky 			if (neigh_type == AF_INET6 &&
574410774bdSArkadi Sharshevsky 			    mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
57518fed7e1SArkadi Sharshevsky 				continue;
57618fed7e1SArkadi Sharshevsky 
577a86f0309SArkadi Sharshevsky 			if (rif_neigh_count < rif_neigh_skip)
578a86f0309SArkadi Sharshevsky 				goto skip;
579a86f0309SArkadi Sharshevsky 
580a86f0309SArkadi Sharshevsky 			mlxsw_sp_dpipe_table_host_entry_fill(mlxsw_sp, entry,
581a86f0309SArkadi Sharshevsky 							     neigh_entry, rif,
582a86f0309SArkadi Sharshevsky 							     type);
583a86f0309SArkadi Sharshevsky 			entry->index = neigh_count;
584a86f0309SArkadi Sharshevsky 			err = devlink_dpipe_entry_ctx_append(dump_ctx, entry);
585a86f0309SArkadi Sharshevsky 			if (err) {
586a86f0309SArkadi Sharshevsky 				if (err == -EMSGSIZE) {
587a86f0309SArkadi Sharshevsky 					if (!j)
588a86f0309SArkadi Sharshevsky 						goto err_entry_append;
589a86f0309SArkadi Sharshevsky 					else
590a86f0309SArkadi Sharshevsky 						goto out;
591a86f0309SArkadi Sharshevsky 				}
592a86f0309SArkadi Sharshevsky 				goto err_entry_append;
593a86f0309SArkadi Sharshevsky 			}
594a86f0309SArkadi Sharshevsky 			neigh_count++;
595a86f0309SArkadi Sharshevsky 			j++;
596a86f0309SArkadi Sharshevsky skip:
597a86f0309SArkadi Sharshevsky 			rif_neigh_count++;
598a86f0309SArkadi Sharshevsky 		}
599a86f0309SArkadi Sharshevsky 		rif_neigh_skip = 0;
600a86f0309SArkadi Sharshevsky 	}
601a86f0309SArkadi Sharshevsky out:
602a86f0309SArkadi Sharshevsky 	devlink_dpipe_entry_ctx_close(dump_ctx);
603a86f0309SArkadi Sharshevsky 	if (i != rif_count)
604a86f0309SArkadi Sharshevsky 		goto start_again;
605a86f0309SArkadi Sharshevsky 
6066a5c69cdSIdo Schimmel 	mutex_unlock(&mlxsw_sp->router->lock);
607a86f0309SArkadi Sharshevsky 	return 0;
608a86f0309SArkadi Sharshevsky 
609a86f0309SArkadi Sharshevsky err_ctx_prepare:
610a86f0309SArkadi Sharshevsky err_entry_append:
6116a5c69cdSIdo Schimmel 	mutex_unlock(&mlxsw_sp->router->lock);
612a86f0309SArkadi Sharshevsky 	return err;
613a86f0309SArkadi Sharshevsky }
614a86f0309SArkadi Sharshevsky 
615a86f0309SArkadi Sharshevsky static int
mlxsw_sp_dpipe_table_host_entries_dump(struct mlxsw_sp * mlxsw_sp,bool counters_enabled,struct devlink_dpipe_dump_ctx * dump_ctx,int type)616a86f0309SArkadi Sharshevsky mlxsw_sp_dpipe_table_host_entries_dump(struct mlxsw_sp *mlxsw_sp,
617a86f0309SArkadi Sharshevsky 				       bool counters_enabled,
618a86f0309SArkadi Sharshevsky 				       struct devlink_dpipe_dump_ctx *dump_ctx,
619a86f0309SArkadi Sharshevsky 				       int type)
620a86f0309SArkadi Sharshevsky {
621a86f0309SArkadi Sharshevsky 	struct devlink_dpipe_value match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT];
622a86f0309SArkadi Sharshevsky 	struct devlink_dpipe_match matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT];
623a86f0309SArkadi Sharshevsky 	struct devlink_dpipe_value action_value;
624a86f0309SArkadi Sharshevsky 	struct devlink_dpipe_action action = {0};
625a86f0309SArkadi Sharshevsky 	struct devlink_dpipe_entry entry = {0};
626a86f0309SArkadi Sharshevsky 	int err;
627a86f0309SArkadi Sharshevsky 
628a86f0309SArkadi Sharshevsky 	memset(matches, 0, MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT *
629a86f0309SArkadi Sharshevsky 			   sizeof(matches[0]));
630a86f0309SArkadi Sharshevsky 	memset(match_values, 0, MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT *
631a86f0309SArkadi Sharshevsky 				sizeof(match_values[0]));
632a86f0309SArkadi Sharshevsky 	memset(&action_value, 0, sizeof(action_value));
633a86f0309SArkadi Sharshevsky 
634a86f0309SArkadi Sharshevsky 	mlxsw_sp_dpipe_table_host_match_action_prepare(matches, &action, type);
635a86f0309SArkadi Sharshevsky 	err = mlxsw_sp_dpipe_table_host_entry_prepare(&entry, match_values,
636a86f0309SArkadi Sharshevsky 						      matches, &action_value,
637a86f0309SArkadi Sharshevsky 						      &action, type);
638a86f0309SArkadi Sharshevsky 	if (err)
639a86f0309SArkadi Sharshevsky 		goto out;
640a86f0309SArkadi Sharshevsky 
641a86f0309SArkadi Sharshevsky 	err = mlxsw_sp_dpipe_table_host_entries_get(mlxsw_sp, &entry,
642a86f0309SArkadi Sharshevsky 						    counters_enabled, dump_ctx,
643a86f0309SArkadi Sharshevsky 						    type);
644a86f0309SArkadi Sharshevsky out:
645a86f0309SArkadi Sharshevsky 	devlink_dpipe_entry_clear(&entry);
646a86f0309SArkadi Sharshevsky 	return err;
647a86f0309SArkadi Sharshevsky }
648a86f0309SArkadi Sharshevsky 
649a86f0309SArkadi Sharshevsky static int
mlxsw_sp_dpipe_table_host4_entries_dump(void * priv,bool counters_enabled,struct devlink_dpipe_dump_ctx * dump_ctx)650a86f0309SArkadi Sharshevsky mlxsw_sp_dpipe_table_host4_entries_dump(void *priv, bool counters_enabled,
651a86f0309SArkadi Sharshevsky 					struct devlink_dpipe_dump_ctx *dump_ctx)
652a86f0309SArkadi Sharshevsky {
653a86f0309SArkadi Sharshevsky 	struct mlxsw_sp *mlxsw_sp = priv;
654a86f0309SArkadi Sharshevsky 
655a86f0309SArkadi Sharshevsky 	return mlxsw_sp_dpipe_table_host_entries_dump(mlxsw_sp,
656a86f0309SArkadi Sharshevsky 						      counters_enabled,
657a86f0309SArkadi Sharshevsky 						      dump_ctx, AF_INET);
658a86f0309SArkadi Sharshevsky }
659a86f0309SArkadi Sharshevsky 
660a481d713SArkadi Sharshevsky static void
mlxsw_sp_dpipe_table_host_counters_update(struct mlxsw_sp * mlxsw_sp,bool enable,int type)661a481d713SArkadi Sharshevsky mlxsw_sp_dpipe_table_host_counters_update(struct mlxsw_sp *mlxsw_sp,
662a481d713SArkadi Sharshevsky 					  bool enable, int type)
663a481d713SArkadi Sharshevsky {
664a481d713SArkadi Sharshevsky 	int i;
665a481d713SArkadi Sharshevsky 
6666a5c69cdSIdo Schimmel 	mutex_lock(&mlxsw_sp->router->lock);
667a481d713SArkadi Sharshevsky 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
668a481d713SArkadi Sharshevsky 		struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
669a481d713SArkadi Sharshevsky 		struct mlxsw_sp_neigh_entry *neigh_entry;
670a481d713SArkadi Sharshevsky 
671a481d713SArkadi Sharshevsky 		if (!rif)
672a481d713SArkadi Sharshevsky 			continue;
673a481d713SArkadi Sharshevsky 		mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {
6740fb5fe3cSArkadi Sharshevsky 			int neigh_type = mlxsw_sp_neigh_entry_type(neigh_entry);
6750fb5fe3cSArkadi Sharshevsky 
6760fb5fe3cSArkadi Sharshevsky 			if (neigh_type != type)
677a481d713SArkadi Sharshevsky 				continue;
6780fb5fe3cSArkadi Sharshevsky 
6790fb5fe3cSArkadi Sharshevsky 			if (neigh_type == AF_INET6 &&
6800fb5fe3cSArkadi Sharshevsky 			    mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
6810fb5fe3cSArkadi Sharshevsky 				continue;
6820fb5fe3cSArkadi Sharshevsky 
683a481d713SArkadi Sharshevsky 			mlxsw_sp_neigh_entry_counter_update(mlxsw_sp,
684a481d713SArkadi Sharshevsky 							    neigh_entry,
685a481d713SArkadi Sharshevsky 							    enable);
686a481d713SArkadi Sharshevsky 		}
687a481d713SArkadi Sharshevsky 	}
6886a5c69cdSIdo Schimmel 	mutex_unlock(&mlxsw_sp->router->lock);
689a481d713SArkadi Sharshevsky }
690a481d713SArkadi Sharshevsky 
mlxsw_sp_dpipe_table_host4_counters_update(void * priv,bool enable)691a481d713SArkadi Sharshevsky static int mlxsw_sp_dpipe_table_host4_counters_update(void *priv, bool enable)
692a481d713SArkadi Sharshevsky {
693a481d713SArkadi Sharshevsky 	struct mlxsw_sp *mlxsw_sp = priv;
694a481d713SArkadi Sharshevsky 
695a481d713SArkadi Sharshevsky 	mlxsw_sp_dpipe_table_host_counters_update(mlxsw_sp, enable, AF_INET);
696a481d713SArkadi Sharshevsky 	return 0;
697a481d713SArkadi Sharshevsky }
698a481d713SArkadi Sharshevsky 
6996aecb36bSArkadi Sharshevsky static u64
mlxsw_sp_dpipe_table_host_size_get(struct mlxsw_sp * mlxsw_sp,int type)7006aecb36bSArkadi Sharshevsky mlxsw_sp_dpipe_table_host_size_get(struct mlxsw_sp *mlxsw_sp, int type)
7016aecb36bSArkadi Sharshevsky {
7026aecb36bSArkadi Sharshevsky 	u64 size = 0;
7036aecb36bSArkadi Sharshevsky 	int i;
7046aecb36bSArkadi Sharshevsky 
7056a5c69cdSIdo Schimmel 	mutex_lock(&mlxsw_sp->router->lock);
7066aecb36bSArkadi Sharshevsky 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
7076aecb36bSArkadi Sharshevsky 		struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
7086aecb36bSArkadi Sharshevsky 		struct mlxsw_sp_neigh_entry *neigh_entry;
7096aecb36bSArkadi Sharshevsky 
7106aecb36bSArkadi Sharshevsky 		if (!rif)
7116aecb36bSArkadi Sharshevsky 			continue;
7126aecb36bSArkadi Sharshevsky 		mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {
713506f7dd5SArkadi Sharshevsky 			int neigh_type = mlxsw_sp_neigh_entry_type(neigh_entry);
714506f7dd5SArkadi Sharshevsky 
715506f7dd5SArkadi Sharshevsky 			if (neigh_type != type)
7166aecb36bSArkadi Sharshevsky 				continue;
717506f7dd5SArkadi Sharshevsky 
718506f7dd5SArkadi Sharshevsky 			if (neigh_type == AF_INET6 &&
719506f7dd5SArkadi Sharshevsky 			    mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
720506f7dd5SArkadi Sharshevsky 				continue;
721506f7dd5SArkadi Sharshevsky 
7226aecb36bSArkadi Sharshevsky 			size++;
7236aecb36bSArkadi Sharshevsky 		}
7246aecb36bSArkadi Sharshevsky 	}
7256a5c69cdSIdo Schimmel 	mutex_unlock(&mlxsw_sp->router->lock);
7266aecb36bSArkadi Sharshevsky 
7276aecb36bSArkadi Sharshevsky 	return size;
7286aecb36bSArkadi Sharshevsky }
7296aecb36bSArkadi Sharshevsky 
mlxsw_sp_dpipe_table_host4_size_get(void * priv)7306aecb36bSArkadi Sharshevsky static u64 mlxsw_sp_dpipe_table_host4_size_get(void *priv)
7316aecb36bSArkadi Sharshevsky {
7326aecb36bSArkadi Sharshevsky 	struct mlxsw_sp *mlxsw_sp = priv;
7336aecb36bSArkadi Sharshevsky 
7346aecb36bSArkadi Sharshevsky 	return mlxsw_sp_dpipe_table_host_size_get(mlxsw_sp, AF_INET);
7356aecb36bSArkadi Sharshevsky }
7366aecb36bSArkadi Sharshevsky 
7376aecb36bSArkadi Sharshevsky static struct devlink_dpipe_table_ops mlxsw_sp_host4_ops = {
7386aecb36bSArkadi Sharshevsky 	.matches_dump = mlxsw_sp_dpipe_table_host4_matches_dump,
739506f7dd5SArkadi Sharshevsky 	.actions_dump = mlxsw_sp_dpipe_table_host_actions_dump,
740a86f0309SArkadi Sharshevsky 	.entries_dump = mlxsw_sp_dpipe_table_host4_entries_dump,
741a481d713SArkadi Sharshevsky 	.counters_set_update = mlxsw_sp_dpipe_table_host4_counters_update,
7426aecb36bSArkadi Sharshevsky 	.size_get = mlxsw_sp_dpipe_table_host4_size_get,
7436aecb36bSArkadi Sharshevsky };
7446aecb36bSArkadi Sharshevsky 
745c0253a45SArkadi Sharshevsky #define MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST4 1
746c0253a45SArkadi Sharshevsky 
mlxsw_sp_dpipe_host4_table_init(struct mlxsw_sp * mlxsw_sp)7476aecb36bSArkadi Sharshevsky static int mlxsw_sp_dpipe_host4_table_init(struct mlxsw_sp *mlxsw_sp)
7486aecb36bSArkadi Sharshevsky {
7496aecb36bSArkadi Sharshevsky 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
750c0253a45SArkadi Sharshevsky 	int err;
7516aecb36bSArkadi Sharshevsky 
75272a4c8c9SJiri Pirko 	err = devl_dpipe_table_register(devlink,
7536aecb36bSArkadi Sharshevsky 					MLXSW_SP_DPIPE_TABLE_NAME_HOST4,
7546aecb36bSArkadi Sharshevsky 					&mlxsw_sp_host4_ops,
7556aecb36bSArkadi Sharshevsky 					mlxsw_sp, false);
756c0253a45SArkadi Sharshevsky 	if (err)
757c0253a45SArkadi Sharshevsky 		return err;
758c0253a45SArkadi Sharshevsky 
75972a4c8c9SJiri Pirko 	err = devl_dpipe_table_resource_set(devlink,
760c0253a45SArkadi Sharshevsky 					    MLXSW_SP_DPIPE_TABLE_NAME_HOST4,
761c0253a45SArkadi Sharshevsky 					    MLXSW_SP_RESOURCE_KVD_HASH_SINGLE,
762c0253a45SArkadi Sharshevsky 					    MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST4);
763c0253a45SArkadi Sharshevsky 	if (err)
764c0253a45SArkadi Sharshevsky 		goto err_resource_set;
765c0253a45SArkadi Sharshevsky 
766c0253a45SArkadi Sharshevsky 	return 0;
767c0253a45SArkadi Sharshevsky 
768c0253a45SArkadi Sharshevsky err_resource_set:
76972a4c8c9SJiri Pirko 	devl_dpipe_table_unregister(devlink,
770c0253a45SArkadi Sharshevsky 				    MLXSW_SP_DPIPE_TABLE_NAME_HOST4);
771c0253a45SArkadi Sharshevsky 	return err;
7726aecb36bSArkadi Sharshevsky }
7736aecb36bSArkadi Sharshevsky 
mlxsw_sp_dpipe_host4_table_fini(struct mlxsw_sp * mlxsw_sp)7746aecb36bSArkadi Sharshevsky static void mlxsw_sp_dpipe_host4_table_fini(struct mlxsw_sp *mlxsw_sp)
7756aecb36bSArkadi Sharshevsky {
7766aecb36bSArkadi Sharshevsky 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
7776aecb36bSArkadi Sharshevsky 
77872a4c8c9SJiri Pirko 	devl_dpipe_table_unregister(devlink,
7796aecb36bSArkadi Sharshevsky 				    MLXSW_SP_DPIPE_TABLE_NAME_HOST4);
7806aecb36bSArkadi Sharshevsky }
7816aecb36bSArkadi Sharshevsky 
782506f7dd5SArkadi Sharshevsky static int
mlxsw_sp_dpipe_table_host6_matches_dump(void * priv,struct sk_buff * skb)783506f7dd5SArkadi Sharshevsky mlxsw_sp_dpipe_table_host6_matches_dump(void *priv, struct sk_buff *skb)
784506f7dd5SArkadi Sharshevsky {
785506f7dd5SArkadi Sharshevsky 	return mlxsw_sp_dpipe_table_host_matches_dump(skb, AF_INET6);
786506f7dd5SArkadi Sharshevsky }
787506f7dd5SArkadi Sharshevsky 
788410774bdSArkadi Sharshevsky static int
mlxsw_sp_dpipe_table_host6_entries_dump(void * priv,bool counters_enabled,struct devlink_dpipe_dump_ctx * dump_ctx)789410774bdSArkadi Sharshevsky mlxsw_sp_dpipe_table_host6_entries_dump(void *priv, bool counters_enabled,
790410774bdSArkadi Sharshevsky 					struct devlink_dpipe_dump_ctx *dump_ctx)
791410774bdSArkadi Sharshevsky {
792410774bdSArkadi Sharshevsky 	struct mlxsw_sp *mlxsw_sp = priv;
793410774bdSArkadi Sharshevsky 
794410774bdSArkadi Sharshevsky 	return mlxsw_sp_dpipe_table_host_entries_dump(mlxsw_sp,
795410774bdSArkadi Sharshevsky 						      counters_enabled,
796410774bdSArkadi Sharshevsky 						      dump_ctx, AF_INET6);
797410774bdSArkadi Sharshevsky }
798410774bdSArkadi Sharshevsky 
mlxsw_sp_dpipe_table_host6_counters_update(void * priv,bool enable)7990fb5fe3cSArkadi Sharshevsky static int mlxsw_sp_dpipe_table_host6_counters_update(void *priv, bool enable)
8000fb5fe3cSArkadi Sharshevsky {
8010fb5fe3cSArkadi Sharshevsky 	struct mlxsw_sp *mlxsw_sp = priv;
8020fb5fe3cSArkadi Sharshevsky 
8030fb5fe3cSArkadi Sharshevsky 	mlxsw_sp_dpipe_table_host_counters_update(mlxsw_sp, enable, AF_INET6);
8040fb5fe3cSArkadi Sharshevsky 	return 0;
8050fb5fe3cSArkadi Sharshevsky }
8060fb5fe3cSArkadi Sharshevsky 
mlxsw_sp_dpipe_table_host6_size_get(void * priv)807506f7dd5SArkadi Sharshevsky static u64 mlxsw_sp_dpipe_table_host6_size_get(void *priv)
808506f7dd5SArkadi Sharshevsky {
809506f7dd5SArkadi Sharshevsky 	struct mlxsw_sp *mlxsw_sp = priv;
810506f7dd5SArkadi Sharshevsky 
811506f7dd5SArkadi Sharshevsky 	return mlxsw_sp_dpipe_table_host_size_get(mlxsw_sp, AF_INET6);
812506f7dd5SArkadi Sharshevsky }
813506f7dd5SArkadi Sharshevsky 
814506f7dd5SArkadi Sharshevsky static struct devlink_dpipe_table_ops mlxsw_sp_host6_ops = {
815506f7dd5SArkadi Sharshevsky 	.matches_dump = mlxsw_sp_dpipe_table_host6_matches_dump,
816506f7dd5SArkadi Sharshevsky 	.actions_dump = mlxsw_sp_dpipe_table_host_actions_dump,
817410774bdSArkadi Sharshevsky 	.entries_dump = mlxsw_sp_dpipe_table_host6_entries_dump,
8180fb5fe3cSArkadi Sharshevsky 	.counters_set_update = mlxsw_sp_dpipe_table_host6_counters_update,
819506f7dd5SArkadi Sharshevsky 	.size_get = mlxsw_sp_dpipe_table_host6_size_get,
820506f7dd5SArkadi Sharshevsky };
821506f7dd5SArkadi Sharshevsky 
822c0253a45SArkadi Sharshevsky #define MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST6 2
823c0253a45SArkadi Sharshevsky 
mlxsw_sp_dpipe_host6_table_init(struct mlxsw_sp * mlxsw_sp)824506f7dd5SArkadi Sharshevsky static int mlxsw_sp_dpipe_host6_table_init(struct mlxsw_sp *mlxsw_sp)
825506f7dd5SArkadi Sharshevsky {
826506f7dd5SArkadi Sharshevsky 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
827c0253a45SArkadi Sharshevsky 	int err;
828506f7dd5SArkadi Sharshevsky 
82972a4c8c9SJiri Pirko 	err = devl_dpipe_table_register(devlink,
830506f7dd5SArkadi Sharshevsky 					MLXSW_SP_DPIPE_TABLE_NAME_HOST6,
831506f7dd5SArkadi Sharshevsky 					&mlxsw_sp_host6_ops,
832506f7dd5SArkadi Sharshevsky 					mlxsw_sp, false);
833c0253a45SArkadi Sharshevsky 	if (err)
834c0253a45SArkadi Sharshevsky 		return err;
835c0253a45SArkadi Sharshevsky 
83672a4c8c9SJiri Pirko 	err = devl_dpipe_table_resource_set(devlink,
837c0253a45SArkadi Sharshevsky 					    MLXSW_SP_DPIPE_TABLE_NAME_HOST6,
838c0253a45SArkadi Sharshevsky 					    MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE,
839c0253a45SArkadi Sharshevsky 					    MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST6);
840c0253a45SArkadi Sharshevsky 	if (err)
841c0253a45SArkadi Sharshevsky 		goto err_resource_set;
842c0253a45SArkadi Sharshevsky 
843c0253a45SArkadi Sharshevsky 	return 0;
844c0253a45SArkadi Sharshevsky 
845c0253a45SArkadi Sharshevsky err_resource_set:
84672a4c8c9SJiri Pirko 	devl_dpipe_table_unregister(devlink,
847c0253a45SArkadi Sharshevsky 				    MLXSW_SP_DPIPE_TABLE_NAME_HOST6);
848c0253a45SArkadi Sharshevsky 	return err;
849506f7dd5SArkadi Sharshevsky }
850506f7dd5SArkadi Sharshevsky 
mlxsw_sp_dpipe_host6_table_fini(struct mlxsw_sp * mlxsw_sp)851506f7dd5SArkadi Sharshevsky static void mlxsw_sp_dpipe_host6_table_fini(struct mlxsw_sp *mlxsw_sp)
852506f7dd5SArkadi Sharshevsky {
853506f7dd5SArkadi Sharshevsky 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
854506f7dd5SArkadi Sharshevsky 
85572a4c8c9SJiri Pirko 	devl_dpipe_table_unregister(devlink,
856506f7dd5SArkadi Sharshevsky 				    MLXSW_SP_DPIPE_TABLE_NAME_HOST6);
857506f7dd5SArkadi Sharshevsky }
858506f7dd5SArkadi Sharshevsky 
mlxsw_sp_dpipe_table_adj_matches_dump(void * priv,struct sk_buff * skb)859c538adb3SArkadi Sharshevsky static int mlxsw_sp_dpipe_table_adj_matches_dump(void *priv,
860c538adb3SArkadi Sharshevsky 						 struct sk_buff *skb)
861c538adb3SArkadi Sharshevsky {
862c538adb3SArkadi Sharshevsky 	struct devlink_dpipe_match match = {0};
863c538adb3SArkadi Sharshevsky 	int err;
864c538adb3SArkadi Sharshevsky 
865c538adb3SArkadi Sharshevsky 	match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
866c538adb3SArkadi Sharshevsky 	match.header = &mlxsw_sp_dpipe_header_metadata;
867c538adb3SArkadi Sharshevsky 	match.field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_INDEX;
868c538adb3SArkadi Sharshevsky 
869c538adb3SArkadi Sharshevsky 	err = devlink_dpipe_match_put(skb, &match);
870c538adb3SArkadi Sharshevsky 	if (err)
871c538adb3SArkadi Sharshevsky 		return err;
872c538adb3SArkadi Sharshevsky 
873c538adb3SArkadi Sharshevsky 	match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
874c538adb3SArkadi Sharshevsky 	match.header = &mlxsw_sp_dpipe_header_metadata;
875e69cd9d7SIdo Schimmel 	match.field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_SIZE;
876e69cd9d7SIdo Schimmel 
877e69cd9d7SIdo Schimmel 	err = devlink_dpipe_match_put(skb, &match);
878e69cd9d7SIdo Schimmel 	if (err)
879e69cd9d7SIdo Schimmel 		return err;
880e69cd9d7SIdo Schimmel 
881e69cd9d7SIdo Schimmel 	match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
882e69cd9d7SIdo Schimmel 	match.header = &mlxsw_sp_dpipe_header_metadata;
883c538adb3SArkadi Sharshevsky 	match.field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_HASH_INDEX;
884c538adb3SArkadi Sharshevsky 
885c538adb3SArkadi Sharshevsky 	return devlink_dpipe_match_put(skb, &match);
886c538adb3SArkadi Sharshevsky }
887c538adb3SArkadi Sharshevsky 
mlxsw_sp_dpipe_table_adj_actions_dump(void * priv,struct sk_buff * skb)888c538adb3SArkadi Sharshevsky static int mlxsw_sp_dpipe_table_adj_actions_dump(void *priv,
889c538adb3SArkadi Sharshevsky 						 struct sk_buff *skb)
890c538adb3SArkadi Sharshevsky {
891c538adb3SArkadi Sharshevsky 	struct devlink_dpipe_action action = {0};
892c538adb3SArkadi Sharshevsky 	int err;
893c538adb3SArkadi Sharshevsky 
894c538adb3SArkadi Sharshevsky 	action.type = DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY;
895c538adb3SArkadi Sharshevsky 	action.header = &devlink_dpipe_header_ethernet;
896c538adb3SArkadi Sharshevsky 	action.field_id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC;
897c538adb3SArkadi Sharshevsky 
898c538adb3SArkadi Sharshevsky 	err = devlink_dpipe_action_put(skb, &action);
899c538adb3SArkadi Sharshevsky 	if (err)
900c538adb3SArkadi Sharshevsky 		return err;
901c538adb3SArkadi Sharshevsky 
902c538adb3SArkadi Sharshevsky 	action.type = DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY;
903c538adb3SArkadi Sharshevsky 	action.header = &mlxsw_sp_dpipe_header_metadata;
904c538adb3SArkadi Sharshevsky 	action.field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT;
905c538adb3SArkadi Sharshevsky 
906c538adb3SArkadi Sharshevsky 	return devlink_dpipe_action_put(skb, &action);
907c538adb3SArkadi Sharshevsky }
908c538adb3SArkadi Sharshevsky 
mlxsw_sp_dpipe_table_adj_size(struct mlxsw_sp * mlxsw_sp)909c538adb3SArkadi Sharshevsky static u64 mlxsw_sp_dpipe_table_adj_size(struct mlxsw_sp *mlxsw_sp)
910c538adb3SArkadi Sharshevsky {
911c538adb3SArkadi Sharshevsky 	struct mlxsw_sp_nexthop *nh;
912c538adb3SArkadi Sharshevsky 	u64 size = 0;
913c538adb3SArkadi Sharshevsky 
914c538adb3SArkadi Sharshevsky 	mlxsw_sp_nexthop_for_each(nh, mlxsw_sp->router)
91526df5accSIdo Schimmel 		if (mlxsw_sp_nexthop_is_forward(nh) &&
91626df5accSIdo Schimmel 		    !mlxsw_sp_nexthop_group_has_ipip(nh))
917c538adb3SArkadi Sharshevsky 			size++;
918c538adb3SArkadi Sharshevsky 	return size;
919c538adb3SArkadi Sharshevsky }
920c538adb3SArkadi Sharshevsky 
921190d38a5SArkadi Sharshevsky enum mlxsw_sp_dpipe_table_adj_match {
922190d38a5SArkadi Sharshevsky 	MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX,
923e69cd9d7SIdo Schimmel 	MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE,
924190d38a5SArkadi Sharshevsky 	MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX,
925190d38a5SArkadi Sharshevsky 	MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT,
926190d38a5SArkadi Sharshevsky };
927190d38a5SArkadi Sharshevsky 
928190d38a5SArkadi Sharshevsky enum mlxsw_sp_dpipe_table_adj_action {
929190d38a5SArkadi Sharshevsky 	MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC,
930190d38a5SArkadi Sharshevsky 	MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT,
931190d38a5SArkadi Sharshevsky 	MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT,
932190d38a5SArkadi Sharshevsky };
933190d38a5SArkadi Sharshevsky 
934190d38a5SArkadi Sharshevsky static void
mlxsw_sp_dpipe_table_adj_match_action_prepare(struct devlink_dpipe_match * matches,struct devlink_dpipe_action * actions)935190d38a5SArkadi Sharshevsky mlxsw_sp_dpipe_table_adj_match_action_prepare(struct devlink_dpipe_match *matches,
936190d38a5SArkadi Sharshevsky 					      struct devlink_dpipe_action *actions)
937190d38a5SArkadi Sharshevsky {
938190d38a5SArkadi Sharshevsky 	struct devlink_dpipe_action *action;
939190d38a5SArkadi Sharshevsky 	struct devlink_dpipe_match *match;
940190d38a5SArkadi Sharshevsky 
941190d38a5SArkadi Sharshevsky 	match = &matches[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX];
942190d38a5SArkadi Sharshevsky 	match->type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
943190d38a5SArkadi Sharshevsky 	match->header = &mlxsw_sp_dpipe_header_metadata;
944190d38a5SArkadi Sharshevsky 	match->field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_INDEX;
945190d38a5SArkadi Sharshevsky 
946e69cd9d7SIdo Schimmel 	match = &matches[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE];
947e69cd9d7SIdo Schimmel 	match->type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
948e69cd9d7SIdo Schimmel 	match->header = &mlxsw_sp_dpipe_header_metadata;
949e69cd9d7SIdo Schimmel 	match->field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_SIZE;
950e69cd9d7SIdo Schimmel 
951190d38a5SArkadi Sharshevsky 	match = &matches[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX];
952190d38a5SArkadi Sharshevsky 	match->type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
953190d38a5SArkadi Sharshevsky 	match->header = &mlxsw_sp_dpipe_header_metadata;
954190d38a5SArkadi Sharshevsky 	match->field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_HASH_INDEX;
955190d38a5SArkadi Sharshevsky 
956190d38a5SArkadi Sharshevsky 	action = &actions[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC];
957190d38a5SArkadi Sharshevsky 	action->type = DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY;
958190d38a5SArkadi Sharshevsky 	action->header = &devlink_dpipe_header_ethernet;
959190d38a5SArkadi Sharshevsky 	action->field_id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC;
960190d38a5SArkadi Sharshevsky 
961190d38a5SArkadi Sharshevsky 	action = &actions[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT];
962190d38a5SArkadi Sharshevsky 	action->type = DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY;
963190d38a5SArkadi Sharshevsky 	action->header = &mlxsw_sp_dpipe_header_metadata;
964190d38a5SArkadi Sharshevsky 	action->field_id = MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT;
965190d38a5SArkadi Sharshevsky }
966190d38a5SArkadi Sharshevsky 
967190d38a5SArkadi Sharshevsky static int
mlxsw_sp_dpipe_table_adj_entry_prepare(struct devlink_dpipe_entry * entry,struct devlink_dpipe_value * match_values,struct devlink_dpipe_match * matches,struct devlink_dpipe_value * action_values,struct devlink_dpipe_action * actions)968190d38a5SArkadi Sharshevsky mlxsw_sp_dpipe_table_adj_entry_prepare(struct devlink_dpipe_entry *entry,
969190d38a5SArkadi Sharshevsky 				       struct devlink_dpipe_value *match_values,
970190d38a5SArkadi Sharshevsky 				       struct devlink_dpipe_match *matches,
971190d38a5SArkadi Sharshevsky 				       struct devlink_dpipe_value *action_values,
972190d38a5SArkadi Sharshevsky 				       struct devlink_dpipe_action *actions)
973190d38a5SArkadi Sharshevsky {	struct devlink_dpipe_value *action_value;
974190d38a5SArkadi Sharshevsky 	struct devlink_dpipe_value *match_value;
975190d38a5SArkadi Sharshevsky 	struct devlink_dpipe_action *action;
976190d38a5SArkadi Sharshevsky 	struct devlink_dpipe_match *match;
977190d38a5SArkadi Sharshevsky 
978190d38a5SArkadi Sharshevsky 	entry->match_values = match_values;
979190d38a5SArkadi Sharshevsky 	entry->match_values_count = MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT;
980190d38a5SArkadi Sharshevsky 
981190d38a5SArkadi Sharshevsky 	entry->action_values = action_values;
982190d38a5SArkadi Sharshevsky 	entry->action_values_count = MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT;
983190d38a5SArkadi Sharshevsky 
984190d38a5SArkadi Sharshevsky 	match = &matches[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX];
985190d38a5SArkadi Sharshevsky 	match_value = &match_values[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX];
986190d38a5SArkadi Sharshevsky 
987190d38a5SArkadi Sharshevsky 	match_value->match = match;
988190d38a5SArkadi Sharshevsky 	match_value->value_size = sizeof(u32);
989190d38a5SArkadi Sharshevsky 	match_value->value = kmalloc(match_value->value_size, GFP_KERNEL);
990190d38a5SArkadi Sharshevsky 	if (!match_value->value)
991190d38a5SArkadi Sharshevsky 		return -ENOMEM;
992190d38a5SArkadi Sharshevsky 
993e69cd9d7SIdo Schimmel 	match = &matches[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE];
994e69cd9d7SIdo Schimmel 	match_value = &match_values[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE];
995e69cd9d7SIdo Schimmel 
996e69cd9d7SIdo Schimmel 	match_value->match = match;
997e69cd9d7SIdo Schimmel 	match_value->value_size = sizeof(u32);
998e69cd9d7SIdo Schimmel 	match_value->value = kmalloc(match_value->value_size, GFP_KERNEL);
999e69cd9d7SIdo Schimmel 	if (!match_value->value)
1000e69cd9d7SIdo Schimmel 		return -ENOMEM;
1001e69cd9d7SIdo Schimmel 
1002190d38a5SArkadi Sharshevsky 	match = &matches[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX];
1003190d38a5SArkadi Sharshevsky 	match_value = &match_values[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX];
1004190d38a5SArkadi Sharshevsky 
1005190d38a5SArkadi Sharshevsky 	match_value->match = match;
1006190d38a5SArkadi Sharshevsky 	match_value->value_size = sizeof(u32);
1007190d38a5SArkadi Sharshevsky 	match_value->value = kmalloc(match_value->value_size, GFP_KERNEL);
1008190d38a5SArkadi Sharshevsky 	if (!match_value->value)
1009190d38a5SArkadi Sharshevsky 		return -ENOMEM;
1010190d38a5SArkadi Sharshevsky 
1011190d38a5SArkadi Sharshevsky 	action = &actions[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC];
1012190d38a5SArkadi Sharshevsky 	action_value = &action_values[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC];
1013190d38a5SArkadi Sharshevsky 
1014190d38a5SArkadi Sharshevsky 	action_value->action = action;
1015190d38a5SArkadi Sharshevsky 	action_value->value_size = sizeof(u64);
1016190d38a5SArkadi Sharshevsky 	action_value->value = kmalloc(action_value->value_size, GFP_KERNEL);
1017190d38a5SArkadi Sharshevsky 	if (!action_value->value)
1018190d38a5SArkadi Sharshevsky 		return -ENOMEM;
1019190d38a5SArkadi Sharshevsky 
1020190d38a5SArkadi Sharshevsky 	action = &actions[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT];
1021190d38a5SArkadi Sharshevsky 	action_value = &action_values[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT];
1022190d38a5SArkadi Sharshevsky 
1023190d38a5SArkadi Sharshevsky 	action_value->action = action;
1024190d38a5SArkadi Sharshevsky 	action_value->value_size = sizeof(u32);
1025190d38a5SArkadi Sharshevsky 	action_value->value = kmalloc(action_value->value_size, GFP_KERNEL);
1026190d38a5SArkadi Sharshevsky 	if (!action_value->value)
1027190d38a5SArkadi Sharshevsky 		return -ENOMEM;
1028190d38a5SArkadi Sharshevsky 
1029190d38a5SArkadi Sharshevsky 	return 0;
1030190d38a5SArkadi Sharshevsky }
1031190d38a5SArkadi Sharshevsky 
1032190d38a5SArkadi Sharshevsky static void
__mlxsw_sp_dpipe_table_adj_entry_fill(struct devlink_dpipe_entry * entry,u32 adj_index,u32 adj_size,u32 adj_hash_index,unsigned char * ha,struct mlxsw_sp_rif * rif)1033190d38a5SArkadi Sharshevsky __mlxsw_sp_dpipe_table_adj_entry_fill(struct devlink_dpipe_entry *entry,
1034e69cd9d7SIdo Schimmel 				      u32 adj_index, u32 adj_size,
1035e69cd9d7SIdo Schimmel 				      u32 adj_hash_index, unsigned char *ha,
1036190d38a5SArkadi Sharshevsky 				      struct mlxsw_sp_rif *rif)
1037190d38a5SArkadi Sharshevsky {
1038190d38a5SArkadi Sharshevsky 	struct devlink_dpipe_value *value;
1039190d38a5SArkadi Sharshevsky 	u32 *p_rif_value;
1040190d38a5SArkadi Sharshevsky 	u32 *p_index;
1041190d38a5SArkadi Sharshevsky 
1042190d38a5SArkadi Sharshevsky 	value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX];
1043190d38a5SArkadi Sharshevsky 	p_index = value->value;
1044190d38a5SArkadi Sharshevsky 	*p_index = adj_index;
1045190d38a5SArkadi Sharshevsky 
1046e69cd9d7SIdo Schimmel 	value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE];
1047e69cd9d7SIdo Schimmel 	p_index = value->value;
1048e69cd9d7SIdo Schimmel 	*p_index = adj_size;
1049e69cd9d7SIdo Schimmel 
1050190d38a5SArkadi Sharshevsky 	value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX];
1051190d38a5SArkadi Sharshevsky 	p_index = value->value;
1052190d38a5SArkadi Sharshevsky 	*p_index = adj_hash_index;
1053190d38a5SArkadi Sharshevsky 
1054190d38a5SArkadi Sharshevsky 	value = &entry->action_values[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC];
1055190d38a5SArkadi Sharshevsky 	ether_addr_copy(value->value, ha);
1056190d38a5SArkadi Sharshevsky 
1057190d38a5SArkadi Sharshevsky 	value = &entry->action_values[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT];
1058190d38a5SArkadi Sharshevsky 	p_rif_value = value->value;
1059190d38a5SArkadi Sharshevsky 	*p_rif_value = mlxsw_sp_rif_index(rif);
1060190d38a5SArkadi Sharshevsky 	value->mapping_value = mlxsw_sp_rif_dev_ifindex(rif);
1061190d38a5SArkadi Sharshevsky 	value->mapping_valid = true;
1062190d38a5SArkadi Sharshevsky }
1063190d38a5SArkadi Sharshevsky 
mlxsw_sp_dpipe_table_adj_entry_fill(struct mlxsw_sp * mlxsw_sp,struct mlxsw_sp_nexthop * nh,struct devlink_dpipe_entry * entry)1064190d38a5SArkadi Sharshevsky static void mlxsw_sp_dpipe_table_adj_entry_fill(struct mlxsw_sp *mlxsw_sp,
1065190d38a5SArkadi Sharshevsky 						struct mlxsw_sp_nexthop *nh,
1066190d38a5SArkadi Sharshevsky 						struct devlink_dpipe_entry *entry)
1067190d38a5SArkadi Sharshevsky {
1068190d38a5SArkadi Sharshevsky 	struct mlxsw_sp_rif *rif = mlxsw_sp_nexthop_rif(nh);
1069190d38a5SArkadi Sharshevsky 	unsigned char *ha = mlxsw_sp_nexthop_ha(nh);
1070190d38a5SArkadi Sharshevsky 	u32 adj_hash_index = 0;
1071190d38a5SArkadi Sharshevsky 	u32 adj_index = 0;
1072e69cd9d7SIdo Schimmel 	u32 adj_size = 0;
1073190d38a5SArkadi Sharshevsky 	int err;
1074190d38a5SArkadi Sharshevsky 
1075e69cd9d7SIdo Schimmel 	mlxsw_sp_nexthop_indexes(nh, &adj_index, &adj_size, &adj_hash_index);
1076e69cd9d7SIdo Schimmel 	__mlxsw_sp_dpipe_table_adj_entry_fill(entry, adj_index, adj_size,
1077190d38a5SArkadi Sharshevsky 					      adj_hash_index, ha, rif);
1078190d38a5SArkadi Sharshevsky 	err = mlxsw_sp_nexthop_counter_get(mlxsw_sp, nh, &entry->counter);
1079190d38a5SArkadi Sharshevsky 	if (!err)
1080190d38a5SArkadi Sharshevsky 		entry->counter_valid = true;
1081190d38a5SArkadi Sharshevsky }
1082190d38a5SArkadi Sharshevsky 
1083190d38a5SArkadi Sharshevsky static int
mlxsw_sp_dpipe_table_adj_entries_get(struct mlxsw_sp * mlxsw_sp,struct devlink_dpipe_entry * entry,bool counters_enabled,struct devlink_dpipe_dump_ctx * dump_ctx)1084190d38a5SArkadi Sharshevsky mlxsw_sp_dpipe_table_adj_entries_get(struct mlxsw_sp *mlxsw_sp,
1085190d38a5SArkadi Sharshevsky 				     struct devlink_dpipe_entry *entry,
1086190d38a5SArkadi Sharshevsky 				     bool counters_enabled,
1087190d38a5SArkadi Sharshevsky 				     struct devlink_dpipe_dump_ctx *dump_ctx)
1088190d38a5SArkadi Sharshevsky {
1089190d38a5SArkadi Sharshevsky 	struct mlxsw_sp_nexthop *nh;
1090190d38a5SArkadi Sharshevsky 	int entry_index = 0;
1091190d38a5SArkadi Sharshevsky 	int nh_count_max;
1092190d38a5SArkadi Sharshevsky 	int nh_count = 0;
1093190d38a5SArkadi Sharshevsky 	int nh_skip;
1094190d38a5SArkadi Sharshevsky 	int j;
1095190d38a5SArkadi Sharshevsky 	int err;
1096190d38a5SArkadi Sharshevsky 
10976a5c69cdSIdo Schimmel 	mutex_lock(&mlxsw_sp->router->lock);
1098190d38a5SArkadi Sharshevsky 	nh_count_max = mlxsw_sp_dpipe_table_adj_size(mlxsw_sp);
1099190d38a5SArkadi Sharshevsky start_again:
1100190d38a5SArkadi Sharshevsky 	err = devlink_dpipe_entry_ctx_prepare(dump_ctx);
1101190d38a5SArkadi Sharshevsky 	if (err)
1102190d38a5SArkadi Sharshevsky 		goto err_ctx_prepare;
1103190d38a5SArkadi Sharshevsky 	j = 0;
1104190d38a5SArkadi Sharshevsky 	nh_skip = nh_count;
110569715dd5SArkadi Sharshevsky 	nh_count = 0;
1106190d38a5SArkadi Sharshevsky 	mlxsw_sp_nexthop_for_each(nh, mlxsw_sp->router) {
110726df5accSIdo Schimmel 		if (!mlxsw_sp_nexthop_is_forward(nh) ||
110826df5accSIdo Schimmel 		    mlxsw_sp_nexthop_group_has_ipip(nh))
1109190d38a5SArkadi Sharshevsky 			continue;
1110190d38a5SArkadi Sharshevsky 
1111190d38a5SArkadi Sharshevsky 		if (nh_count < nh_skip)
1112190d38a5SArkadi Sharshevsky 			goto skip;
1113190d38a5SArkadi Sharshevsky 
1114190d38a5SArkadi Sharshevsky 		mlxsw_sp_dpipe_table_adj_entry_fill(mlxsw_sp, nh, entry);
1115190d38a5SArkadi Sharshevsky 		entry->index = entry_index;
1116190d38a5SArkadi Sharshevsky 		err = devlink_dpipe_entry_ctx_append(dump_ctx, entry);
1117190d38a5SArkadi Sharshevsky 		if (err) {
1118190d38a5SArkadi Sharshevsky 			if (err == -EMSGSIZE) {
1119190d38a5SArkadi Sharshevsky 				if (!j)
1120190d38a5SArkadi Sharshevsky 					goto err_entry_append;
1121190d38a5SArkadi Sharshevsky 				break;
1122190d38a5SArkadi Sharshevsky 			}
1123190d38a5SArkadi Sharshevsky 			goto err_entry_append;
1124190d38a5SArkadi Sharshevsky 		}
1125190d38a5SArkadi Sharshevsky 		entry_index++;
1126190d38a5SArkadi Sharshevsky 		j++;
1127190d38a5SArkadi Sharshevsky skip:
1128190d38a5SArkadi Sharshevsky 		nh_count++;
1129190d38a5SArkadi Sharshevsky 	}
1130190d38a5SArkadi Sharshevsky 
1131190d38a5SArkadi Sharshevsky 	devlink_dpipe_entry_ctx_close(dump_ctx);
1132190d38a5SArkadi Sharshevsky 	if (nh_count != nh_count_max)
1133190d38a5SArkadi Sharshevsky 		goto start_again;
11346a5c69cdSIdo Schimmel 	mutex_unlock(&mlxsw_sp->router->lock);
1135190d38a5SArkadi Sharshevsky 
1136190d38a5SArkadi Sharshevsky 	return 0;
1137190d38a5SArkadi Sharshevsky 
1138190d38a5SArkadi Sharshevsky err_ctx_prepare:
1139190d38a5SArkadi Sharshevsky err_entry_append:
11406a5c69cdSIdo Schimmel 	mutex_unlock(&mlxsw_sp->router->lock);
1141190d38a5SArkadi Sharshevsky 	return err;
1142190d38a5SArkadi Sharshevsky }
1143190d38a5SArkadi Sharshevsky 
1144190d38a5SArkadi Sharshevsky static int
mlxsw_sp_dpipe_table_adj_entries_dump(void * priv,bool counters_enabled,struct devlink_dpipe_dump_ctx * dump_ctx)1145190d38a5SArkadi Sharshevsky mlxsw_sp_dpipe_table_adj_entries_dump(void *priv, bool counters_enabled,
1146190d38a5SArkadi Sharshevsky 				      struct devlink_dpipe_dump_ctx *dump_ctx)
1147190d38a5SArkadi Sharshevsky {
1148190d38a5SArkadi Sharshevsky 	struct devlink_dpipe_value action_values[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT];
1149190d38a5SArkadi Sharshevsky 	struct devlink_dpipe_value match_values[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT];
1150190d38a5SArkadi Sharshevsky 	struct devlink_dpipe_action actions[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT];
1151190d38a5SArkadi Sharshevsky 	struct devlink_dpipe_match matches[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT];
1152190d38a5SArkadi Sharshevsky 	struct devlink_dpipe_entry entry = {0};
1153190d38a5SArkadi Sharshevsky 	struct mlxsw_sp *mlxsw_sp = priv;
1154190d38a5SArkadi Sharshevsky 	int err;
1155190d38a5SArkadi Sharshevsky 
1156190d38a5SArkadi Sharshevsky 	memset(matches, 0, MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT *
1157190d38a5SArkadi Sharshevsky 			   sizeof(matches[0]));
1158190d38a5SArkadi Sharshevsky 	memset(match_values, 0, MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT *
1159190d38a5SArkadi Sharshevsky 				sizeof(match_values[0]));
1160190d38a5SArkadi Sharshevsky 	memset(actions, 0, MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT *
1161190d38a5SArkadi Sharshevsky 			   sizeof(actions[0]));
1162190d38a5SArkadi Sharshevsky 	memset(action_values, 0, MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT *
1163190d38a5SArkadi Sharshevsky 				 sizeof(action_values[0]));
1164190d38a5SArkadi Sharshevsky 
1165190d38a5SArkadi Sharshevsky 	mlxsw_sp_dpipe_table_adj_match_action_prepare(matches, actions);
1166190d38a5SArkadi Sharshevsky 	err = mlxsw_sp_dpipe_table_adj_entry_prepare(&entry,
1167190d38a5SArkadi Sharshevsky 						     match_values, matches,
1168190d38a5SArkadi Sharshevsky 						     action_values, actions);
1169190d38a5SArkadi Sharshevsky 	if (err)
1170190d38a5SArkadi Sharshevsky 		goto out;
1171190d38a5SArkadi Sharshevsky 
1172190d38a5SArkadi Sharshevsky 	err = mlxsw_sp_dpipe_table_adj_entries_get(mlxsw_sp, &entry,
1173190d38a5SArkadi Sharshevsky 						   counters_enabled, dump_ctx);
1174190d38a5SArkadi Sharshevsky out:
1175190d38a5SArkadi Sharshevsky 	devlink_dpipe_entry_clear(&entry);
1176190d38a5SArkadi Sharshevsky 	return err;
1177190d38a5SArkadi Sharshevsky }
1178190d38a5SArkadi Sharshevsky 
mlxsw_sp_dpipe_table_adj_counters_update(void * priv,bool enable)1179427e652aSArkadi Sharshevsky static int mlxsw_sp_dpipe_table_adj_counters_update(void *priv, bool enable)
1180427e652aSArkadi Sharshevsky {
1181197fdfd1SIdo Schimmel 	char ratr_pl[MLXSW_REG_RATR_LEN];
1182427e652aSArkadi Sharshevsky 	struct mlxsw_sp *mlxsw_sp = priv;
1183427e652aSArkadi Sharshevsky 	struct mlxsw_sp_nexthop *nh;
1184427e652aSArkadi Sharshevsky 	u32 adj_hash_index = 0;
1185427e652aSArkadi Sharshevsky 	u32 adj_index = 0;
1186e69cd9d7SIdo Schimmel 	u32 adj_size = 0;
1187427e652aSArkadi Sharshevsky 
1188427e652aSArkadi Sharshevsky 	mlxsw_sp_nexthop_for_each(nh, mlxsw_sp->router) {
118926df5accSIdo Schimmel 		if (!mlxsw_sp_nexthop_is_forward(nh) ||
119026df5accSIdo Schimmel 		    mlxsw_sp_nexthop_group_has_ipip(nh))
1191427e652aSArkadi Sharshevsky 			continue;
1192427e652aSArkadi Sharshevsky 
1193e69cd9d7SIdo Schimmel 		mlxsw_sp_nexthop_indexes(nh, &adj_index, &adj_size,
1194e69cd9d7SIdo Schimmel 					 &adj_hash_index);
1195427e652aSArkadi Sharshevsky 		if (enable)
1196427e652aSArkadi Sharshevsky 			mlxsw_sp_nexthop_counter_alloc(mlxsw_sp, nh);
1197427e652aSArkadi Sharshevsky 		else
1198427e652aSArkadi Sharshevsky 			mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
1199424603ccSIdo Schimmel 		mlxsw_sp_nexthop_eth_update(mlxsw_sp,
120062b67ff3SIdo Schimmel 					    adj_index + adj_hash_index, nh,
1201197fdfd1SIdo Schimmel 					    true, ratr_pl);
1202427e652aSArkadi Sharshevsky 	}
1203427e652aSArkadi Sharshevsky 	return 0;
1204427e652aSArkadi Sharshevsky }
1205427e652aSArkadi Sharshevsky 
1206c538adb3SArkadi Sharshevsky static u64
mlxsw_sp_dpipe_table_adj_size_get(void * priv)1207c538adb3SArkadi Sharshevsky mlxsw_sp_dpipe_table_adj_size_get(void *priv)
1208c538adb3SArkadi Sharshevsky {
1209c538adb3SArkadi Sharshevsky 	struct mlxsw_sp *mlxsw_sp = priv;
1210c538adb3SArkadi Sharshevsky 	u64 size;
1211c538adb3SArkadi Sharshevsky 
12126a5c69cdSIdo Schimmel 	mutex_lock(&mlxsw_sp->router->lock);
1213c538adb3SArkadi Sharshevsky 	size = mlxsw_sp_dpipe_table_adj_size(mlxsw_sp);
12146a5c69cdSIdo Schimmel 	mutex_unlock(&mlxsw_sp->router->lock);
1215c538adb3SArkadi Sharshevsky 
1216c538adb3SArkadi Sharshevsky 	return size;
1217c538adb3SArkadi Sharshevsky }
1218c538adb3SArkadi Sharshevsky 
1219c538adb3SArkadi Sharshevsky static struct devlink_dpipe_table_ops mlxsw_sp_dpipe_table_adj_ops = {
1220c538adb3SArkadi Sharshevsky 	.matches_dump = mlxsw_sp_dpipe_table_adj_matches_dump,
1221c538adb3SArkadi Sharshevsky 	.actions_dump = mlxsw_sp_dpipe_table_adj_actions_dump,
1222190d38a5SArkadi Sharshevsky 	.entries_dump = mlxsw_sp_dpipe_table_adj_entries_dump,
1223427e652aSArkadi Sharshevsky 	.counters_set_update = mlxsw_sp_dpipe_table_adj_counters_update,
1224c538adb3SArkadi Sharshevsky 	.size_get = mlxsw_sp_dpipe_table_adj_size_get,
1225c538adb3SArkadi Sharshevsky };
1226c538adb3SArkadi Sharshevsky 
1227c0253a45SArkadi Sharshevsky #define MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_ADJ 1
1228c0253a45SArkadi Sharshevsky 
mlxsw_sp_dpipe_adj_table_init(struct mlxsw_sp * mlxsw_sp)1229c538adb3SArkadi Sharshevsky static int mlxsw_sp_dpipe_adj_table_init(struct mlxsw_sp *mlxsw_sp)
1230c538adb3SArkadi Sharshevsky {
1231c538adb3SArkadi Sharshevsky 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1232c0253a45SArkadi Sharshevsky 	int err;
1233c538adb3SArkadi Sharshevsky 
123472a4c8c9SJiri Pirko 	err = devl_dpipe_table_register(devlink,
1235c538adb3SArkadi Sharshevsky 					MLXSW_SP_DPIPE_TABLE_NAME_ADJ,
1236c538adb3SArkadi Sharshevsky 					&mlxsw_sp_dpipe_table_adj_ops,
1237c538adb3SArkadi Sharshevsky 					mlxsw_sp, false);
1238c0253a45SArkadi Sharshevsky 	if (err)
1239c0253a45SArkadi Sharshevsky 		return err;
1240c0253a45SArkadi Sharshevsky 
124172a4c8c9SJiri Pirko 	err = devl_dpipe_table_resource_set(devlink,
1242c0253a45SArkadi Sharshevsky 					    MLXSW_SP_DPIPE_TABLE_NAME_ADJ,
1243c0253a45SArkadi Sharshevsky 					    MLXSW_SP_RESOURCE_KVD_LINEAR,
1244c0253a45SArkadi Sharshevsky 					    MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_ADJ);
1245c0253a45SArkadi Sharshevsky 	if (err)
1246c0253a45SArkadi Sharshevsky 		goto err_resource_set;
1247c0253a45SArkadi Sharshevsky 
1248c0253a45SArkadi Sharshevsky 	return 0;
1249c0253a45SArkadi Sharshevsky 
1250c0253a45SArkadi Sharshevsky err_resource_set:
125172a4c8c9SJiri Pirko 	devl_dpipe_table_unregister(devlink,
1252c0253a45SArkadi Sharshevsky 				    MLXSW_SP_DPIPE_TABLE_NAME_ADJ);
1253c0253a45SArkadi Sharshevsky 	return err;
1254c538adb3SArkadi Sharshevsky }
1255c538adb3SArkadi Sharshevsky 
mlxsw_sp_dpipe_adj_table_fini(struct mlxsw_sp * mlxsw_sp)1256c538adb3SArkadi Sharshevsky static void mlxsw_sp_dpipe_adj_table_fini(struct mlxsw_sp *mlxsw_sp)
1257c538adb3SArkadi Sharshevsky {
1258c538adb3SArkadi Sharshevsky 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1259c538adb3SArkadi Sharshevsky 
126072a4c8c9SJiri Pirko 	devl_dpipe_table_unregister(devlink,
1261c538adb3SArkadi Sharshevsky 				    MLXSW_SP_DPIPE_TABLE_NAME_ADJ);
1262c538adb3SArkadi Sharshevsky }
1263c538adb3SArkadi Sharshevsky 
mlxsw_sp_dpipe_init(struct mlxsw_sp * mlxsw_sp)1264230ead01SArkadi Sharshevsky int mlxsw_sp_dpipe_init(struct mlxsw_sp *mlxsw_sp)
1265230ead01SArkadi Sharshevsky {
1266d54b70feSArkadi Sharshevsky 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1267d54b70feSArkadi Sharshevsky 	int err;
1268d54b70feSArkadi Sharshevsky 
126972a4c8c9SJiri Pirko 	devl_dpipe_headers_register(devlink, &mlxsw_sp_dpipe_headers);
12709a792366SJiri Pirko 
1271d54b70feSArkadi Sharshevsky 	err = mlxsw_sp_dpipe_erif_table_init(mlxsw_sp);
1272d54b70feSArkadi Sharshevsky 	if (err)
12737e57ae9fSArkadi Sharshevsky 		goto err_erif_table_init;
12746aecb36bSArkadi Sharshevsky 
12756aecb36bSArkadi Sharshevsky 	err = mlxsw_sp_dpipe_host4_table_init(mlxsw_sp);
12766aecb36bSArkadi Sharshevsky 	if (err)
12776aecb36bSArkadi Sharshevsky 		goto err_host4_table_init;
1278506f7dd5SArkadi Sharshevsky 
1279506f7dd5SArkadi Sharshevsky 	err = mlxsw_sp_dpipe_host6_table_init(mlxsw_sp);
1280506f7dd5SArkadi Sharshevsky 	if (err)
1281506f7dd5SArkadi Sharshevsky 		goto err_host6_table_init;
1282d54b70feSArkadi Sharshevsky 
1283c538adb3SArkadi Sharshevsky 	err = mlxsw_sp_dpipe_adj_table_init(mlxsw_sp);
1284c538adb3SArkadi Sharshevsky 	if (err)
1285c538adb3SArkadi Sharshevsky 		goto err_adj_table_init;
1286c538adb3SArkadi Sharshevsky 
1287c538adb3SArkadi Sharshevsky 	return 0;
1288c538adb3SArkadi Sharshevsky err_adj_table_init:
1289c538adb3SArkadi Sharshevsky 	mlxsw_sp_dpipe_host6_table_fini(mlxsw_sp);
1290506f7dd5SArkadi Sharshevsky err_host6_table_init:
1291506f7dd5SArkadi Sharshevsky 	mlxsw_sp_dpipe_host4_table_fini(mlxsw_sp);
12926aecb36bSArkadi Sharshevsky err_host4_table_init:
12936aecb36bSArkadi Sharshevsky 	mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp);
12947e57ae9fSArkadi Sharshevsky err_erif_table_init:
129572a4c8c9SJiri Pirko 	devl_dpipe_headers_unregister(priv_to_devlink(mlxsw_sp->core));
1296d54b70feSArkadi Sharshevsky 	return err;
1297230ead01SArkadi Sharshevsky }
1298230ead01SArkadi Sharshevsky 
mlxsw_sp_dpipe_fini(struct mlxsw_sp * mlxsw_sp)1299230ead01SArkadi Sharshevsky void mlxsw_sp_dpipe_fini(struct mlxsw_sp *mlxsw_sp)
1300230ead01SArkadi Sharshevsky {
1301d54b70feSArkadi Sharshevsky 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1302d54b70feSArkadi Sharshevsky 
1303c538adb3SArkadi Sharshevsky 	mlxsw_sp_dpipe_adj_table_fini(mlxsw_sp);
1304506f7dd5SArkadi Sharshevsky 	mlxsw_sp_dpipe_host6_table_fini(mlxsw_sp);
13056aecb36bSArkadi Sharshevsky 	mlxsw_sp_dpipe_host4_table_fini(mlxsw_sp);
1306d54b70feSArkadi Sharshevsky 	mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp);
130772a4c8c9SJiri Pirko 	devl_dpipe_headers_unregister(devlink);
1308230ead01SArkadi Sharshevsky }
1309