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