2 * drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
3 * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
4 * Copyright (c) 2017 Arkadi Sharshevsky <arakdis@mellanox.com>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the names of the copyright holders nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * Alternatively, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") version 2 as published by the Free
20 * Software Foundation.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
35 #include <linux/kernel.h>
36 #include <net/devlink.h>
39 #include "spectrum_dpipe.h"
40 #include "spectrum_router.h"
42 enum mlxsw_sp_field_metadata_id
{
43 MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
,
44 MLXSW_SP_DPIPE_FIELD_METADATA_L3_FORWARD
,
45 MLXSW_SP_DPIPE_FIELD_METADATA_L3_DROP
,
46 MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_INDEX
,
47 MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_SIZE
,
48 MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_HASH_INDEX
,
51 static struct devlink_dpipe_field mlxsw_sp_dpipe_fields_metadata
[] = {
54 .id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
,
56 .mapping_type
= DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX
,
60 .id
= MLXSW_SP_DPIPE_FIELD_METADATA_L3_FORWARD
,
65 .id
= MLXSW_SP_DPIPE_FIELD_METADATA_L3_DROP
,
70 .id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_INDEX
,
75 .id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_SIZE
,
79 .name
= "adj_hash_index",
80 .id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_HASH_INDEX
,
85 enum mlxsw_sp_dpipe_header_id
{
86 MLXSW_SP_DPIPE_HEADER_METADATA
,
89 static struct devlink_dpipe_header mlxsw_sp_dpipe_header_metadata
= {
91 .id
= MLXSW_SP_DPIPE_HEADER_METADATA
,
92 .fields
= mlxsw_sp_dpipe_fields_metadata
,
93 .fields_count
= ARRAY_SIZE(mlxsw_sp_dpipe_fields_metadata
),
96 static struct devlink_dpipe_header
*mlxsw_dpipe_headers
[] = {
97 &mlxsw_sp_dpipe_header_metadata
,
98 &devlink_dpipe_header_ethernet
,
99 &devlink_dpipe_header_ipv4
,
100 &devlink_dpipe_header_ipv6
,
103 static struct devlink_dpipe_headers mlxsw_sp_dpipe_headers
= {
104 .headers
= mlxsw_dpipe_headers
,
105 .headers_count
= ARRAY_SIZE(mlxsw_dpipe_headers
),
108 static int mlxsw_sp_dpipe_table_erif_actions_dump(void *priv
,
111 struct devlink_dpipe_action action
= {0};
114 action
.type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
115 action
.header
= &mlxsw_sp_dpipe_header_metadata
;
116 action
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_L3_FORWARD
;
118 err
= devlink_dpipe_action_put(skb
, &action
);
122 action
.type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
123 action
.header
= &mlxsw_sp_dpipe_header_metadata
;
124 action
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_L3_DROP
;
126 return devlink_dpipe_action_put(skb
, &action
);
129 static int mlxsw_sp_dpipe_table_erif_matches_dump(void *priv
,
132 struct devlink_dpipe_match match
= {0};
134 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
135 match
.header
= &mlxsw_sp_dpipe_header_metadata
;
136 match
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
;
138 return devlink_dpipe_match_put(skb
, &match
);
142 mlxsw_sp_erif_match_action_prepare(struct devlink_dpipe_match
*match
,
143 struct devlink_dpipe_action
*action
)
145 action
->type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
146 action
->header
= &mlxsw_sp_dpipe_header_metadata
;
147 action
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_L3_FORWARD
;
149 match
->type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
150 match
->header
= &mlxsw_sp_dpipe_header_metadata
;
151 match
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
;
154 static int mlxsw_sp_erif_entry_prepare(struct devlink_dpipe_entry
*entry
,
155 struct devlink_dpipe_value
*match_value
,
156 struct devlink_dpipe_match
*match
,
157 struct devlink_dpipe_value
*action_value
,
158 struct devlink_dpipe_action
*action
)
160 entry
->match_values
= match_value
;
161 entry
->match_values_count
= 1;
163 entry
->action_values
= action_value
;
164 entry
->action_values_count
= 1;
166 match_value
->match
= match
;
167 match_value
->value_size
= sizeof(u32
);
168 match_value
->value
= kmalloc(match_value
->value_size
, GFP_KERNEL
);
169 if (!match_value
->value
)
172 action_value
->action
= action
;
173 action_value
->value_size
= sizeof(u32
);
174 action_value
->value
= kmalloc(action_value
->value_size
, GFP_KERNEL
);
175 if (!action_value
->value
)
176 goto err_action_alloc
;
180 kfree(match_value
->value
);
184 static int mlxsw_sp_erif_entry_get(struct mlxsw_sp
*mlxsw_sp
,
185 struct devlink_dpipe_entry
*entry
,
186 struct mlxsw_sp_rif
*rif
,
187 bool counters_enabled
)
194 /* Set Match RIF index */
195 rif_value
= entry
->match_values
->value
;
196 *rif_value
= mlxsw_sp_rif_index(rif
);
197 entry
->match_values
->mapping_value
= mlxsw_sp_rif_dev_ifindex(rif
);
198 entry
->match_values
->mapping_valid
= true;
200 /* Set Action Forwarding */
201 action_value
= entry
->action_values
->value
;
204 entry
->counter_valid
= false;
206 entry
->index
= mlxsw_sp_rif_index(rif
);
208 if (!counters_enabled
)
211 err
= mlxsw_sp_rif_counter_value_get(mlxsw_sp
, rif
,
212 MLXSW_SP_RIF_COUNTER_EGRESS
,
215 entry
->counter
= cnt
;
216 entry
->counter_valid
= true;
222 mlxsw_sp_dpipe_table_erif_entries_dump(void *priv
, bool counters_enabled
,
223 struct devlink_dpipe_dump_ctx
*dump_ctx
)
225 struct devlink_dpipe_value match_value
, action_value
;
226 struct devlink_dpipe_action action
= {0};
227 struct devlink_dpipe_match match
= {0};
228 struct devlink_dpipe_entry entry
= {0};
229 struct mlxsw_sp
*mlxsw_sp
= priv
;
230 unsigned int rif_count
;
234 memset(&match_value
, 0, sizeof(match_value
));
235 memset(&action_value
, 0, sizeof(action_value
));
237 mlxsw_sp_erif_match_action_prepare(&match
, &action
);
238 err
= mlxsw_sp_erif_entry_prepare(&entry
, &match_value
, &match
,
239 &action_value
, &action
);
243 rif_count
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
247 err
= devlink_dpipe_entry_ctx_prepare(dump_ctx
);
251 for (; i
< rif_count
; i
++) {
252 struct mlxsw_sp_rif
*rif
= mlxsw_sp_rif_by_index(mlxsw_sp
, i
);
256 err
= mlxsw_sp_erif_entry_get(mlxsw_sp
, &entry
, rif
,
260 err
= devlink_dpipe_entry_ctx_append(dump_ctx
, &entry
);
262 if (err
== -EMSGSIZE
) {
264 goto err_entry_append
;
267 goto err_entry_append
;
272 devlink_dpipe_entry_ctx_close(dump_ctx
);
277 devlink_dpipe_entry_clear(&entry
);
282 devlink_dpipe_entry_clear(&entry
);
286 static int mlxsw_sp_dpipe_table_erif_counters_update(void *priv
, bool enable
)
288 struct mlxsw_sp
*mlxsw_sp
= priv
;
292 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++) {
293 struct mlxsw_sp_rif
*rif
= mlxsw_sp_rif_by_index(mlxsw_sp
, i
);
298 mlxsw_sp_rif_counter_alloc(mlxsw_sp
, rif
,
299 MLXSW_SP_RIF_COUNTER_EGRESS
);
301 mlxsw_sp_rif_counter_free(mlxsw_sp
, rif
,
302 MLXSW_SP_RIF_COUNTER_EGRESS
);
308 static u64
mlxsw_sp_dpipe_table_erif_size_get(void *priv
)
310 struct mlxsw_sp
*mlxsw_sp
= priv
;
312 return MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
315 static struct devlink_dpipe_table_ops mlxsw_sp_erif_ops
= {
316 .matches_dump
= mlxsw_sp_dpipe_table_erif_matches_dump
,
317 .actions_dump
= mlxsw_sp_dpipe_table_erif_actions_dump
,
318 .entries_dump
= mlxsw_sp_dpipe_table_erif_entries_dump
,
319 .counters_set_update
= mlxsw_sp_dpipe_table_erif_counters_update
,
320 .size_get
= mlxsw_sp_dpipe_table_erif_size_get
,
323 static int mlxsw_sp_dpipe_erif_table_init(struct mlxsw_sp
*mlxsw_sp
)
325 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
327 return devlink_dpipe_table_register(devlink
,
328 MLXSW_SP_DPIPE_TABLE_NAME_ERIF
,
333 static void mlxsw_sp_dpipe_erif_table_fini(struct mlxsw_sp
*mlxsw_sp
)
335 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
337 devlink_dpipe_table_unregister(devlink
, MLXSW_SP_DPIPE_TABLE_NAME_ERIF
);
340 static int mlxsw_sp_dpipe_table_host_matches_dump(struct sk_buff
*skb
, int type
)
342 struct devlink_dpipe_match match
= {0};
345 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
346 match
.header
= &mlxsw_sp_dpipe_header_metadata
;
347 match
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
;
349 err
= devlink_dpipe_match_put(skb
, &match
);
355 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
356 match
.header
= &devlink_dpipe_header_ipv4
;
357 match
.field_id
= DEVLINK_DPIPE_FIELD_IPV4_DST_IP
;
360 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
361 match
.header
= &devlink_dpipe_header_ipv6
;
362 match
.field_id
= DEVLINK_DPIPE_FIELD_IPV6_DST_IP
;
369 return devlink_dpipe_match_put(skb
, &match
);
373 mlxsw_sp_dpipe_table_host4_matches_dump(void *priv
, struct sk_buff
*skb
)
375 return mlxsw_sp_dpipe_table_host_matches_dump(skb
, AF_INET
);
379 mlxsw_sp_dpipe_table_host_actions_dump(void *priv
, struct sk_buff
*skb
)
381 struct devlink_dpipe_action action
= {0};
383 action
.type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
384 action
.header
= &devlink_dpipe_header_ethernet
;
385 action
.field_id
= DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC
;
387 return devlink_dpipe_action_put(skb
, &action
);
390 enum mlxsw_sp_dpipe_table_host_match
{
391 MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF
,
392 MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP
,
393 MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT
,
397 mlxsw_sp_dpipe_table_host_match_action_prepare(struct devlink_dpipe_match
*matches
,
398 struct devlink_dpipe_action
*action
,
401 struct devlink_dpipe_match
*match
;
403 match
= &matches
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF
];
404 match
->type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
405 match
->header
= &mlxsw_sp_dpipe_header_metadata
;
406 match
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
;
408 match
= &matches
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP
];
409 match
->type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
412 match
->header
= &devlink_dpipe_header_ipv4
;
413 match
->field_id
= DEVLINK_DPIPE_FIELD_IPV4_DST_IP
;
416 match
->header
= &devlink_dpipe_header_ipv6
;
417 match
->field_id
= DEVLINK_DPIPE_FIELD_IPV6_DST_IP
;
424 action
->type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
425 action
->header
= &devlink_dpipe_header_ethernet
;
426 action
->field_id
= DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC
;
430 mlxsw_sp_dpipe_table_host_entry_prepare(struct devlink_dpipe_entry
*entry
,
431 struct devlink_dpipe_value
*match_values
,
432 struct devlink_dpipe_match
*matches
,
433 struct devlink_dpipe_value
*action_value
,
434 struct devlink_dpipe_action
*action
,
437 struct devlink_dpipe_value
*match_value
;
438 struct devlink_dpipe_match
*match
;
440 entry
->match_values
= match_values
;
441 entry
->match_values_count
= MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT
;
443 entry
->action_values
= action_value
;
444 entry
->action_values_count
= 1;
446 match
= &matches
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF
];
447 match_value
= &match_values
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF
];
449 match_value
->match
= match
;
450 match_value
->value_size
= sizeof(u32
);
451 match_value
->value
= kmalloc(match_value
->value_size
, GFP_KERNEL
);
452 if (!match_value
->value
)
455 match
= &matches
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP
];
456 match_value
= &match_values
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP
];
458 match_value
->match
= match
;
461 match_value
->value_size
= sizeof(u32
);
464 match_value
->value_size
= sizeof(struct in6_addr
);
471 match_value
->value
= kmalloc(match_value
->value_size
, GFP_KERNEL
);
472 if (!match_value
->value
)
475 action_value
->action
= action
;
476 action_value
->value_size
= sizeof(u64
);
477 action_value
->value
= kmalloc(action_value
->value_size
, GFP_KERNEL
);
478 if (!action_value
->value
)
485 __mlxsw_sp_dpipe_table_host_entry_fill(struct devlink_dpipe_entry
*entry
,
486 struct mlxsw_sp_rif
*rif
,
487 unsigned char *ha
, void *dip
)
489 struct devlink_dpipe_value
*value
;
493 /* Set Match RIF index */
494 value
= &entry
->match_values
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF
];
496 rif_value
= value
->value
;
497 *rif_value
= mlxsw_sp_rif_index(rif
);
498 value
->mapping_value
= mlxsw_sp_rif_dev_ifindex(rif
);
499 value
->mapping_valid
= true;
502 value
= &entry
->match_values
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP
];
503 memcpy(value
->value
, dip
, value
->value_size
);
505 /* Set Action DMAC */
506 value
= entry
->action_values
;
507 ha_value
= value
->value
;
508 ether_addr_copy(ha_value
, ha
);
512 mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry
*entry
,
513 struct mlxsw_sp_neigh_entry
*neigh_entry
,
514 struct mlxsw_sp_rif
*rif
)
519 ha
= mlxsw_sp_neigh_entry_ha(neigh_entry
);
520 dip
= mlxsw_sp_neigh4_entry_dip(neigh_entry
);
521 __mlxsw_sp_dpipe_table_host_entry_fill(entry
, rif
, ha
, &dip
);
525 mlxsw_sp_dpipe_table_host6_entry_fill(struct devlink_dpipe_entry
*entry
,
526 struct mlxsw_sp_neigh_entry
*neigh_entry
,
527 struct mlxsw_sp_rif
*rif
)
529 struct in6_addr
*dip
;
532 ha
= mlxsw_sp_neigh_entry_ha(neigh_entry
);
533 dip
= mlxsw_sp_neigh6_entry_dip(neigh_entry
);
535 __mlxsw_sp_dpipe_table_host_entry_fill(entry
, rif
, ha
, dip
);
539 mlxsw_sp_dpipe_table_host_entry_fill(struct mlxsw_sp
*mlxsw_sp
,
540 struct devlink_dpipe_entry
*entry
,
541 struct mlxsw_sp_neigh_entry
*neigh_entry
,
542 struct mlxsw_sp_rif
*rif
,
549 mlxsw_sp_dpipe_table_host4_entry_fill(entry
, neigh_entry
, rif
);
552 mlxsw_sp_dpipe_table_host6_entry_fill(entry
, neigh_entry
, rif
);
559 err
= mlxsw_sp_neigh_counter_get(mlxsw_sp
, neigh_entry
,
562 entry
->counter_valid
= true;
566 mlxsw_sp_dpipe_table_host_entries_get(struct mlxsw_sp
*mlxsw_sp
,
567 struct devlink_dpipe_entry
*entry
,
568 bool counters_enabled
,
569 struct devlink_dpipe_dump_ctx
*dump_ctx
,
572 int rif_neigh_count
= 0;
573 int rif_neigh_skip
= 0;
581 rif_count
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
583 err
= devlink_dpipe_entry_ctx_prepare(dump_ctx
);
585 goto err_ctx_prepare
;
587 rif_neigh_skip
= rif_neigh_count
;
588 for (; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++) {
589 struct mlxsw_sp_rif
*rif
= mlxsw_sp_rif_by_index(mlxsw_sp
, i
);
590 struct mlxsw_sp_neigh_entry
*neigh_entry
;
596 mlxsw_sp_rif_neigh_for_each(neigh_entry
, rif
) {
597 int neigh_type
= mlxsw_sp_neigh_entry_type(neigh_entry
);
599 if (neigh_type
!= type
)
602 if (neigh_type
== AF_INET6
&&
603 mlxsw_sp_neigh_ipv6_ignore(neigh_entry
))
606 if (rif_neigh_count
< rif_neigh_skip
)
609 mlxsw_sp_dpipe_table_host_entry_fill(mlxsw_sp
, entry
,
612 entry
->index
= neigh_count
;
613 err
= devlink_dpipe_entry_ctx_append(dump_ctx
, entry
);
615 if (err
== -EMSGSIZE
) {
617 goto err_entry_append
;
621 goto err_entry_append
;
631 devlink_dpipe_entry_ctx_close(dump_ctx
);
645 mlxsw_sp_dpipe_table_host_entries_dump(struct mlxsw_sp
*mlxsw_sp
,
646 bool counters_enabled
,
647 struct devlink_dpipe_dump_ctx
*dump_ctx
,
650 struct devlink_dpipe_value match_values
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT
];
651 struct devlink_dpipe_match matches
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT
];
652 struct devlink_dpipe_value action_value
;
653 struct devlink_dpipe_action action
= {0};
654 struct devlink_dpipe_entry entry
= {0};
657 memset(matches
, 0, MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT
*
659 memset(match_values
, 0, MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT
*
660 sizeof(match_values
[0]));
661 memset(&action_value
, 0, sizeof(action_value
));
663 mlxsw_sp_dpipe_table_host_match_action_prepare(matches
, &action
, type
);
664 err
= mlxsw_sp_dpipe_table_host_entry_prepare(&entry
, match_values
,
665 matches
, &action_value
,
670 err
= mlxsw_sp_dpipe_table_host_entries_get(mlxsw_sp
, &entry
,
671 counters_enabled
, dump_ctx
,
674 devlink_dpipe_entry_clear(&entry
);
679 mlxsw_sp_dpipe_table_host4_entries_dump(void *priv
, bool counters_enabled
,
680 struct devlink_dpipe_dump_ctx
*dump_ctx
)
682 struct mlxsw_sp
*mlxsw_sp
= priv
;
684 return mlxsw_sp_dpipe_table_host_entries_dump(mlxsw_sp
,
690 mlxsw_sp_dpipe_table_host_counters_update(struct mlxsw_sp
*mlxsw_sp
,
691 bool enable
, int type
)
696 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++) {
697 struct mlxsw_sp_rif
*rif
= mlxsw_sp_rif_by_index(mlxsw_sp
, i
);
698 struct mlxsw_sp_neigh_entry
*neigh_entry
;
702 mlxsw_sp_rif_neigh_for_each(neigh_entry
, rif
) {
703 int neigh_type
= mlxsw_sp_neigh_entry_type(neigh_entry
);
705 if (neigh_type
!= type
)
708 if (neigh_type
== AF_INET6
&&
709 mlxsw_sp_neigh_ipv6_ignore(neigh_entry
))
712 mlxsw_sp_neigh_entry_counter_update(mlxsw_sp
,
720 static int mlxsw_sp_dpipe_table_host4_counters_update(void *priv
, bool enable
)
722 struct mlxsw_sp
*mlxsw_sp
= priv
;
724 mlxsw_sp_dpipe_table_host_counters_update(mlxsw_sp
, enable
, AF_INET
);
729 mlxsw_sp_dpipe_table_host_size_get(struct mlxsw_sp
*mlxsw_sp
, int type
)
735 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++) {
736 struct mlxsw_sp_rif
*rif
= mlxsw_sp_rif_by_index(mlxsw_sp
, i
);
737 struct mlxsw_sp_neigh_entry
*neigh_entry
;
741 mlxsw_sp_rif_neigh_for_each(neigh_entry
, rif
) {
742 int neigh_type
= mlxsw_sp_neigh_entry_type(neigh_entry
);
744 if (neigh_type
!= type
)
747 if (neigh_type
== AF_INET6
&&
748 mlxsw_sp_neigh_ipv6_ignore(neigh_entry
))
759 static u64
mlxsw_sp_dpipe_table_host4_size_get(void *priv
)
761 struct mlxsw_sp
*mlxsw_sp
= priv
;
763 return mlxsw_sp_dpipe_table_host_size_get(mlxsw_sp
, AF_INET
);
766 static struct devlink_dpipe_table_ops mlxsw_sp_host4_ops
= {
767 .matches_dump
= mlxsw_sp_dpipe_table_host4_matches_dump
,
768 .actions_dump
= mlxsw_sp_dpipe_table_host_actions_dump
,
769 .entries_dump
= mlxsw_sp_dpipe_table_host4_entries_dump
,
770 .counters_set_update
= mlxsw_sp_dpipe_table_host4_counters_update
,
771 .size_get
= mlxsw_sp_dpipe_table_host4_size_get
,
774 #define MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST4 1
776 static int mlxsw_sp_dpipe_host4_table_init(struct mlxsw_sp
*mlxsw_sp
)
778 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
781 err
= devlink_dpipe_table_register(devlink
,
782 MLXSW_SP_DPIPE_TABLE_NAME_HOST4
,
788 err
= devlink_dpipe_table_resource_set(devlink
,
789 MLXSW_SP_DPIPE_TABLE_NAME_HOST4
,
790 MLXSW_SP_RESOURCE_KVD_HASH_SINGLE
,
791 MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST4
);
793 goto err_resource_set
;
798 devlink_dpipe_table_unregister(devlink
,
799 MLXSW_SP_DPIPE_TABLE_NAME_HOST4
);
803 static void mlxsw_sp_dpipe_host4_table_fini(struct mlxsw_sp
*mlxsw_sp
)
805 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
807 devlink_dpipe_table_unregister(devlink
,
808 MLXSW_SP_DPIPE_TABLE_NAME_HOST4
);
812 mlxsw_sp_dpipe_table_host6_matches_dump(void *priv
, struct sk_buff
*skb
)
814 return mlxsw_sp_dpipe_table_host_matches_dump(skb
, AF_INET6
);
818 mlxsw_sp_dpipe_table_host6_entries_dump(void *priv
, bool counters_enabled
,
819 struct devlink_dpipe_dump_ctx
*dump_ctx
)
821 struct mlxsw_sp
*mlxsw_sp
= priv
;
823 return mlxsw_sp_dpipe_table_host_entries_dump(mlxsw_sp
,
828 static int mlxsw_sp_dpipe_table_host6_counters_update(void *priv
, bool enable
)
830 struct mlxsw_sp
*mlxsw_sp
= priv
;
832 mlxsw_sp_dpipe_table_host_counters_update(mlxsw_sp
, enable
, AF_INET6
);
836 static u64
mlxsw_sp_dpipe_table_host6_size_get(void *priv
)
838 struct mlxsw_sp
*mlxsw_sp
= priv
;
840 return mlxsw_sp_dpipe_table_host_size_get(mlxsw_sp
, AF_INET6
);
843 static struct devlink_dpipe_table_ops mlxsw_sp_host6_ops
= {
844 .matches_dump
= mlxsw_sp_dpipe_table_host6_matches_dump
,
845 .actions_dump
= mlxsw_sp_dpipe_table_host_actions_dump
,
846 .entries_dump
= mlxsw_sp_dpipe_table_host6_entries_dump
,
847 .counters_set_update
= mlxsw_sp_dpipe_table_host6_counters_update
,
848 .size_get
= mlxsw_sp_dpipe_table_host6_size_get
,
851 #define MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST6 2
853 static int mlxsw_sp_dpipe_host6_table_init(struct mlxsw_sp
*mlxsw_sp
)
855 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
858 err
= devlink_dpipe_table_register(devlink
,
859 MLXSW_SP_DPIPE_TABLE_NAME_HOST6
,
865 err
= devlink_dpipe_table_resource_set(devlink
,
866 MLXSW_SP_DPIPE_TABLE_NAME_HOST6
,
867 MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE
,
868 MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST6
);
870 goto err_resource_set
;
875 devlink_dpipe_table_unregister(devlink
,
876 MLXSW_SP_DPIPE_TABLE_NAME_HOST6
);
880 static void mlxsw_sp_dpipe_host6_table_fini(struct mlxsw_sp
*mlxsw_sp
)
882 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
884 devlink_dpipe_table_unregister(devlink
,
885 MLXSW_SP_DPIPE_TABLE_NAME_HOST6
);
888 static int mlxsw_sp_dpipe_table_adj_matches_dump(void *priv
,
891 struct devlink_dpipe_match match
= {0};
894 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
895 match
.header
= &mlxsw_sp_dpipe_header_metadata
;
896 match
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_INDEX
;
898 err
= devlink_dpipe_match_put(skb
, &match
);
902 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
903 match
.header
= &mlxsw_sp_dpipe_header_metadata
;
904 match
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_SIZE
;
906 err
= devlink_dpipe_match_put(skb
, &match
);
910 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
911 match
.header
= &mlxsw_sp_dpipe_header_metadata
;
912 match
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_HASH_INDEX
;
914 return devlink_dpipe_match_put(skb
, &match
);
917 static int mlxsw_sp_dpipe_table_adj_actions_dump(void *priv
,
920 struct devlink_dpipe_action action
= {0};
923 action
.type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
924 action
.header
= &devlink_dpipe_header_ethernet
;
925 action
.field_id
= DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC
;
927 err
= devlink_dpipe_action_put(skb
, &action
);
931 action
.type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
932 action
.header
= &mlxsw_sp_dpipe_header_metadata
;
933 action
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
;
935 return devlink_dpipe_action_put(skb
, &action
);
938 static u64
mlxsw_sp_dpipe_table_adj_size(struct mlxsw_sp
*mlxsw_sp
)
940 struct mlxsw_sp_nexthop
*nh
;
943 mlxsw_sp_nexthop_for_each(nh
, mlxsw_sp
->router
)
944 if (mlxsw_sp_nexthop_offload(nh
) &&
945 !mlxsw_sp_nexthop_group_has_ipip(nh
))
950 enum mlxsw_sp_dpipe_table_adj_match
{
951 MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX
,
952 MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE
,
953 MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX
,
954 MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT
,
957 enum mlxsw_sp_dpipe_table_adj_action
{
958 MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC
,
959 MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT
,
960 MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT
,
964 mlxsw_sp_dpipe_table_adj_match_action_prepare(struct devlink_dpipe_match
*matches
,
965 struct devlink_dpipe_action
*actions
)
967 struct devlink_dpipe_action
*action
;
968 struct devlink_dpipe_match
*match
;
970 match
= &matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX
];
971 match
->type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
972 match
->header
= &mlxsw_sp_dpipe_header_metadata
;
973 match
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_INDEX
;
975 match
= &matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE
];
976 match
->type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
977 match
->header
= &mlxsw_sp_dpipe_header_metadata
;
978 match
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_SIZE
;
980 match
= &matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX
];
981 match
->type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
982 match
->header
= &mlxsw_sp_dpipe_header_metadata
;
983 match
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_HASH_INDEX
;
985 action
= &actions
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC
];
986 action
->type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
987 action
->header
= &devlink_dpipe_header_ethernet
;
988 action
->field_id
= DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC
;
990 action
= &actions
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT
];
991 action
->type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
992 action
->header
= &mlxsw_sp_dpipe_header_metadata
;
993 action
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
;
997 mlxsw_sp_dpipe_table_adj_entry_prepare(struct devlink_dpipe_entry
*entry
,
998 struct devlink_dpipe_value
*match_values
,
999 struct devlink_dpipe_match
*matches
,
1000 struct devlink_dpipe_value
*action_values
,
1001 struct devlink_dpipe_action
*actions
)
1002 { struct devlink_dpipe_value
*action_value
;
1003 struct devlink_dpipe_value
*match_value
;
1004 struct devlink_dpipe_action
*action
;
1005 struct devlink_dpipe_match
*match
;
1007 entry
->match_values
= match_values
;
1008 entry
->match_values_count
= MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT
;
1010 entry
->action_values
= action_values
;
1011 entry
->action_values_count
= MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT
;
1013 match
= &matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX
];
1014 match_value
= &match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX
];
1016 match_value
->match
= match
;
1017 match_value
->value_size
= sizeof(u32
);
1018 match_value
->value
= kmalloc(match_value
->value_size
, GFP_KERNEL
);
1019 if (!match_value
->value
)
1022 match
= &matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE
];
1023 match_value
= &match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE
];
1025 match_value
->match
= match
;
1026 match_value
->value_size
= sizeof(u32
);
1027 match_value
->value
= kmalloc(match_value
->value_size
, GFP_KERNEL
);
1028 if (!match_value
->value
)
1031 match
= &matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX
];
1032 match_value
= &match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX
];
1034 match_value
->match
= match
;
1035 match_value
->value_size
= sizeof(u32
);
1036 match_value
->value
= kmalloc(match_value
->value_size
, GFP_KERNEL
);
1037 if (!match_value
->value
)
1040 action
= &actions
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC
];
1041 action_value
= &action_values
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC
];
1043 action_value
->action
= action
;
1044 action_value
->value_size
= sizeof(u64
);
1045 action_value
->value
= kmalloc(action_value
->value_size
, GFP_KERNEL
);
1046 if (!action_value
->value
)
1049 action
= &actions
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT
];
1050 action_value
= &action_values
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT
];
1052 action_value
->action
= action
;
1053 action_value
->value_size
= sizeof(u32
);
1054 action_value
->value
= kmalloc(action_value
->value_size
, GFP_KERNEL
);
1055 if (!action_value
->value
)
1062 __mlxsw_sp_dpipe_table_adj_entry_fill(struct devlink_dpipe_entry
*entry
,
1063 u32 adj_index
, u32 adj_size
,
1064 u32 adj_hash_index
, unsigned char *ha
,
1065 struct mlxsw_sp_rif
*rif
)
1067 struct devlink_dpipe_value
*value
;
1071 value
= &entry
->match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX
];
1072 p_index
= value
->value
;
1073 *p_index
= adj_index
;
1075 value
= &entry
->match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE
];
1076 p_index
= value
->value
;
1077 *p_index
= adj_size
;
1079 value
= &entry
->match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX
];
1080 p_index
= value
->value
;
1081 *p_index
= adj_hash_index
;
1083 value
= &entry
->action_values
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC
];
1084 ether_addr_copy(value
->value
, ha
);
1086 value
= &entry
->action_values
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT
];
1087 p_rif_value
= value
->value
;
1088 *p_rif_value
= mlxsw_sp_rif_index(rif
);
1089 value
->mapping_value
= mlxsw_sp_rif_dev_ifindex(rif
);
1090 value
->mapping_valid
= true;
1093 static void mlxsw_sp_dpipe_table_adj_entry_fill(struct mlxsw_sp
*mlxsw_sp
,
1094 struct mlxsw_sp_nexthop
*nh
,
1095 struct devlink_dpipe_entry
*entry
)
1097 struct mlxsw_sp_rif
*rif
= mlxsw_sp_nexthop_rif(nh
);
1098 unsigned char *ha
= mlxsw_sp_nexthop_ha(nh
);
1099 u32 adj_hash_index
= 0;
1104 mlxsw_sp_nexthop_indexes(nh
, &adj_index
, &adj_size
, &adj_hash_index
);
1105 __mlxsw_sp_dpipe_table_adj_entry_fill(entry
, adj_index
, adj_size
,
1106 adj_hash_index
, ha
, rif
);
1107 err
= mlxsw_sp_nexthop_counter_get(mlxsw_sp
, nh
, &entry
->counter
);
1109 entry
->counter_valid
= true;
1113 mlxsw_sp_dpipe_table_adj_entries_get(struct mlxsw_sp
*mlxsw_sp
,
1114 struct devlink_dpipe_entry
*entry
,
1115 bool counters_enabled
,
1116 struct devlink_dpipe_dump_ctx
*dump_ctx
)
1118 struct mlxsw_sp_nexthop
*nh
;
1119 int entry_index
= 0;
1127 nh_count_max
= mlxsw_sp_dpipe_table_adj_size(mlxsw_sp
);
1129 err
= devlink_dpipe_entry_ctx_prepare(dump_ctx
);
1131 goto err_ctx_prepare
;
1135 mlxsw_sp_nexthop_for_each(nh
, mlxsw_sp
->router
) {
1136 if (!mlxsw_sp_nexthop_offload(nh
) ||
1137 mlxsw_sp_nexthop_group_has_ipip(nh
))
1140 if (nh_count
< nh_skip
)
1143 mlxsw_sp_dpipe_table_adj_entry_fill(mlxsw_sp
, nh
, entry
);
1144 entry
->index
= entry_index
;
1145 err
= devlink_dpipe_entry_ctx_append(dump_ctx
, entry
);
1147 if (err
== -EMSGSIZE
) {
1149 goto err_entry_append
;
1152 goto err_entry_append
;
1160 devlink_dpipe_entry_ctx_close(dump_ctx
);
1161 if (nh_count
!= nh_count_max
)
1174 mlxsw_sp_dpipe_table_adj_entries_dump(void *priv
, bool counters_enabled
,
1175 struct devlink_dpipe_dump_ctx
*dump_ctx
)
1177 struct devlink_dpipe_value action_values
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT
];
1178 struct devlink_dpipe_value match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT
];
1179 struct devlink_dpipe_action actions
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT
];
1180 struct devlink_dpipe_match matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT
];
1181 struct devlink_dpipe_entry entry
= {0};
1182 struct mlxsw_sp
*mlxsw_sp
= priv
;
1185 memset(matches
, 0, MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT
*
1186 sizeof(matches
[0]));
1187 memset(match_values
, 0, MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT
*
1188 sizeof(match_values
[0]));
1189 memset(actions
, 0, MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT
*
1190 sizeof(actions
[0]));
1191 memset(action_values
, 0, MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT
*
1192 sizeof(action_values
[0]));
1194 mlxsw_sp_dpipe_table_adj_match_action_prepare(matches
, actions
);
1195 err
= mlxsw_sp_dpipe_table_adj_entry_prepare(&entry
,
1196 match_values
, matches
,
1197 action_values
, actions
);
1201 err
= mlxsw_sp_dpipe_table_adj_entries_get(mlxsw_sp
, &entry
,
1202 counters_enabled
, dump_ctx
);
1204 devlink_dpipe_entry_clear(&entry
);
1208 static int mlxsw_sp_dpipe_table_adj_counters_update(void *priv
, bool enable
)
1210 struct mlxsw_sp
*mlxsw_sp
= priv
;
1211 struct mlxsw_sp_nexthop
*nh
;
1212 u32 adj_hash_index
= 0;
1216 mlxsw_sp_nexthop_for_each(nh
, mlxsw_sp
->router
) {
1217 if (!mlxsw_sp_nexthop_offload(nh
) ||
1218 mlxsw_sp_nexthop_group_has_ipip(nh
))
1221 mlxsw_sp_nexthop_indexes(nh
, &adj_index
, &adj_size
,
1224 mlxsw_sp_nexthop_counter_alloc(mlxsw_sp
, nh
);
1226 mlxsw_sp_nexthop_counter_free(mlxsw_sp
, nh
);
1227 mlxsw_sp_nexthop_update(mlxsw_sp
,
1228 adj_index
+ adj_hash_index
, nh
);
1234 mlxsw_sp_dpipe_table_adj_size_get(void *priv
)
1236 struct mlxsw_sp
*mlxsw_sp
= priv
;
1240 size
= mlxsw_sp_dpipe_table_adj_size(mlxsw_sp
);
1246 static struct devlink_dpipe_table_ops mlxsw_sp_dpipe_table_adj_ops
= {
1247 .matches_dump
= mlxsw_sp_dpipe_table_adj_matches_dump
,
1248 .actions_dump
= mlxsw_sp_dpipe_table_adj_actions_dump
,
1249 .entries_dump
= mlxsw_sp_dpipe_table_adj_entries_dump
,
1250 .counters_set_update
= mlxsw_sp_dpipe_table_adj_counters_update
,
1251 .size_get
= mlxsw_sp_dpipe_table_adj_size_get
,
1254 #define MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_ADJ 1
1256 static int mlxsw_sp_dpipe_adj_table_init(struct mlxsw_sp
*mlxsw_sp
)
1258 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
1261 err
= devlink_dpipe_table_register(devlink
,
1262 MLXSW_SP_DPIPE_TABLE_NAME_ADJ
,
1263 &mlxsw_sp_dpipe_table_adj_ops
,
1268 err
= devlink_dpipe_table_resource_set(devlink
,
1269 MLXSW_SP_DPIPE_TABLE_NAME_ADJ
,
1270 MLXSW_SP_RESOURCE_KVD_LINEAR
,
1271 MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_ADJ
);
1273 goto err_resource_set
;
1278 devlink_dpipe_table_unregister(devlink
,
1279 MLXSW_SP_DPIPE_TABLE_NAME_ADJ
);
1283 static void mlxsw_sp_dpipe_adj_table_fini(struct mlxsw_sp
*mlxsw_sp
)
1285 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
1287 devlink_dpipe_table_unregister(devlink
,
1288 MLXSW_SP_DPIPE_TABLE_NAME_ADJ
);
1291 int mlxsw_sp_dpipe_init(struct mlxsw_sp
*mlxsw_sp
)
1293 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
1296 err
= devlink_dpipe_headers_register(devlink
,
1297 &mlxsw_sp_dpipe_headers
);
1300 err
= mlxsw_sp_dpipe_erif_table_init(mlxsw_sp
);
1302 goto err_erif_table_init
;
1304 err
= mlxsw_sp_dpipe_host4_table_init(mlxsw_sp
);
1306 goto err_host4_table_init
;
1308 err
= mlxsw_sp_dpipe_host6_table_init(mlxsw_sp
);
1310 goto err_host6_table_init
;
1312 err
= mlxsw_sp_dpipe_adj_table_init(mlxsw_sp
);
1314 goto err_adj_table_init
;
1318 mlxsw_sp_dpipe_host6_table_fini(mlxsw_sp
);
1319 err_host6_table_init
:
1320 mlxsw_sp_dpipe_host4_table_fini(mlxsw_sp
);
1321 err_host4_table_init
:
1322 mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp
);
1323 err_erif_table_init
:
1324 devlink_dpipe_headers_unregister(priv_to_devlink(mlxsw_sp
->core
));
1328 void mlxsw_sp_dpipe_fini(struct mlxsw_sp
*mlxsw_sp
)
1330 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
1332 mlxsw_sp_dpipe_adj_table_fini(mlxsw_sp
);
1333 mlxsw_sp_dpipe_host6_table_fini(mlxsw_sp
);
1334 mlxsw_sp_dpipe_host4_table_fini(mlxsw_sp
);
1335 mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp
);
1336 devlink_dpipe_headers_unregister(devlink
);