1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
4 #include <linux/kernel.h>
5 #include <linux/mutex.h>
6 #include <net/devlink.h>
9 #include "spectrum_dpipe.h"
10 #include "spectrum_router.h"
12 enum mlxsw_sp_field_metadata_id
{
13 MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
,
14 MLXSW_SP_DPIPE_FIELD_METADATA_L3_FORWARD
,
15 MLXSW_SP_DPIPE_FIELD_METADATA_L3_DROP
,
16 MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_INDEX
,
17 MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_SIZE
,
18 MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_HASH_INDEX
,
21 static struct devlink_dpipe_field mlxsw_sp_dpipe_fields_metadata
[] = {
24 .id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
,
26 .mapping_type
= DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX
,
30 .id
= MLXSW_SP_DPIPE_FIELD_METADATA_L3_FORWARD
,
35 .id
= MLXSW_SP_DPIPE_FIELD_METADATA_L3_DROP
,
40 .id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_INDEX
,
45 .id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_SIZE
,
49 .name
= "adj_hash_index",
50 .id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_HASH_INDEX
,
55 enum mlxsw_sp_dpipe_header_id
{
56 MLXSW_SP_DPIPE_HEADER_METADATA
,
59 static struct devlink_dpipe_header mlxsw_sp_dpipe_header_metadata
= {
61 .id
= MLXSW_SP_DPIPE_HEADER_METADATA
,
62 .fields
= mlxsw_sp_dpipe_fields_metadata
,
63 .fields_count
= ARRAY_SIZE(mlxsw_sp_dpipe_fields_metadata
),
66 static struct devlink_dpipe_header
*mlxsw_dpipe_headers
[] = {
67 &mlxsw_sp_dpipe_header_metadata
,
68 &devlink_dpipe_header_ethernet
,
69 &devlink_dpipe_header_ipv4
,
70 &devlink_dpipe_header_ipv6
,
73 static struct devlink_dpipe_headers mlxsw_sp_dpipe_headers
= {
74 .headers
= mlxsw_dpipe_headers
,
75 .headers_count
= ARRAY_SIZE(mlxsw_dpipe_headers
),
78 static int mlxsw_sp_dpipe_table_erif_actions_dump(void *priv
,
81 struct devlink_dpipe_action action
= {0};
84 action
.type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
85 action
.header
= &mlxsw_sp_dpipe_header_metadata
;
86 action
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_L3_FORWARD
;
88 err
= devlink_dpipe_action_put(skb
, &action
);
92 action
.type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
93 action
.header
= &mlxsw_sp_dpipe_header_metadata
;
94 action
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_L3_DROP
;
96 return devlink_dpipe_action_put(skb
, &action
);
99 static int mlxsw_sp_dpipe_table_erif_matches_dump(void *priv
,
102 struct devlink_dpipe_match match
= {0};
104 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
105 match
.header
= &mlxsw_sp_dpipe_header_metadata
;
106 match
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
;
108 return devlink_dpipe_match_put(skb
, &match
);
112 mlxsw_sp_erif_match_action_prepare(struct devlink_dpipe_match
*match
,
113 struct devlink_dpipe_action
*action
)
115 action
->type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
116 action
->header
= &mlxsw_sp_dpipe_header_metadata
;
117 action
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_L3_FORWARD
;
119 match
->type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
120 match
->header
= &mlxsw_sp_dpipe_header_metadata
;
121 match
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
;
124 static int mlxsw_sp_erif_entry_prepare(struct devlink_dpipe_entry
*entry
,
125 struct devlink_dpipe_value
*match_value
,
126 struct devlink_dpipe_match
*match
,
127 struct devlink_dpipe_value
*action_value
,
128 struct devlink_dpipe_action
*action
)
130 entry
->match_values
= match_value
;
131 entry
->match_values_count
= 1;
133 entry
->action_values
= action_value
;
134 entry
->action_values_count
= 1;
136 match_value
->match
= match
;
137 match_value
->value_size
= sizeof(u32
);
138 match_value
->value
= kmalloc(match_value
->value_size
, GFP_KERNEL
);
139 if (!match_value
->value
)
142 action_value
->action
= action
;
143 action_value
->value_size
= sizeof(u32
);
144 action_value
->value
= kmalloc(action_value
->value_size
, GFP_KERNEL
);
145 if (!action_value
->value
)
146 goto err_action_alloc
;
150 kfree(match_value
->value
);
154 static int mlxsw_sp_erif_entry_get(struct mlxsw_sp
*mlxsw_sp
,
155 struct devlink_dpipe_entry
*entry
,
156 struct mlxsw_sp_rif
*rif
,
157 bool counters_enabled
)
164 /* Set Match RIF index */
165 rif_value
= entry
->match_values
->value
;
166 *rif_value
= mlxsw_sp_rif_index(rif
);
167 entry
->match_values
->mapping_value
= mlxsw_sp_rif_dev_ifindex(rif
);
168 entry
->match_values
->mapping_valid
= true;
170 /* Set Action Forwarding */
171 action_value
= entry
->action_values
->value
;
174 entry
->counter_valid
= false;
176 entry
->index
= mlxsw_sp_rif_index(rif
);
178 if (!counters_enabled
)
181 err
= mlxsw_sp_rif_counter_value_get(mlxsw_sp
, rif
,
182 MLXSW_SP_RIF_COUNTER_EGRESS
,
185 entry
->counter
= cnt
;
186 entry
->counter_valid
= true;
192 mlxsw_sp_dpipe_table_erif_entries_dump(void *priv
, bool counters_enabled
,
193 struct devlink_dpipe_dump_ctx
*dump_ctx
)
195 struct devlink_dpipe_value match_value
, action_value
;
196 struct devlink_dpipe_action action
= {0};
197 struct devlink_dpipe_match match
= {0};
198 struct devlink_dpipe_entry entry
= {0};
199 struct mlxsw_sp
*mlxsw_sp
= priv
;
200 unsigned int rif_count
;
204 memset(&match_value
, 0, sizeof(match_value
));
205 memset(&action_value
, 0, sizeof(action_value
));
207 mlxsw_sp_erif_match_action_prepare(&match
, &action
);
208 err
= mlxsw_sp_erif_entry_prepare(&entry
, &match_value
, &match
,
209 &action_value
, &action
);
213 rif_count
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
214 mutex_lock(&mlxsw_sp
->router
->lock
);
217 err
= devlink_dpipe_entry_ctx_prepare(dump_ctx
);
219 goto err_ctx_prepare
;
221 for (; i
< rif_count
; i
++) {
222 struct mlxsw_sp_rif
*rif
= mlxsw_sp_rif_by_index(mlxsw_sp
, i
);
224 if (!rif
|| !mlxsw_sp_rif_dev(rif
))
226 err
= mlxsw_sp_erif_entry_get(mlxsw_sp
, &entry
, rif
,
230 err
= devlink_dpipe_entry_ctx_append(dump_ctx
, &entry
);
232 if (err
== -EMSGSIZE
) {
234 goto err_entry_append
;
237 goto err_entry_append
;
242 devlink_dpipe_entry_ctx_close(dump_ctx
);
245 mutex_unlock(&mlxsw_sp
->router
->lock
);
247 devlink_dpipe_entry_clear(&entry
);
252 mutex_unlock(&mlxsw_sp
->router
->lock
);
253 devlink_dpipe_entry_clear(&entry
);
257 static int mlxsw_sp_dpipe_table_erif_counters_update(void *priv
, bool enable
)
259 struct mlxsw_sp
*mlxsw_sp
= priv
;
262 mutex_lock(&mlxsw_sp
->router
->lock
);
263 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++) {
264 struct mlxsw_sp_rif
*rif
= mlxsw_sp_rif_by_index(mlxsw_sp
, i
);
269 mlxsw_sp_rif_counter_alloc(mlxsw_sp
, rif
,
270 MLXSW_SP_RIF_COUNTER_EGRESS
);
272 mlxsw_sp_rif_counter_free(mlxsw_sp
, rif
,
273 MLXSW_SP_RIF_COUNTER_EGRESS
);
275 mutex_unlock(&mlxsw_sp
->router
->lock
);
279 static u64
mlxsw_sp_dpipe_table_erif_size_get(void *priv
)
281 struct mlxsw_sp
*mlxsw_sp
= priv
;
283 return MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
286 static struct devlink_dpipe_table_ops mlxsw_sp_erif_ops
= {
287 .matches_dump
= mlxsw_sp_dpipe_table_erif_matches_dump
,
288 .actions_dump
= mlxsw_sp_dpipe_table_erif_actions_dump
,
289 .entries_dump
= mlxsw_sp_dpipe_table_erif_entries_dump
,
290 .counters_set_update
= mlxsw_sp_dpipe_table_erif_counters_update
,
291 .size_get
= mlxsw_sp_dpipe_table_erif_size_get
,
294 static int mlxsw_sp_dpipe_erif_table_init(struct mlxsw_sp
*mlxsw_sp
)
296 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
298 return devlink_dpipe_table_register(devlink
,
299 MLXSW_SP_DPIPE_TABLE_NAME_ERIF
,
304 static void mlxsw_sp_dpipe_erif_table_fini(struct mlxsw_sp
*mlxsw_sp
)
306 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
308 devlink_dpipe_table_unregister(devlink
, MLXSW_SP_DPIPE_TABLE_NAME_ERIF
);
311 static int mlxsw_sp_dpipe_table_host_matches_dump(struct sk_buff
*skb
, int type
)
313 struct devlink_dpipe_match match
= {0};
316 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
317 match
.header
= &mlxsw_sp_dpipe_header_metadata
;
318 match
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
;
320 err
= devlink_dpipe_match_put(skb
, &match
);
326 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
327 match
.header
= &devlink_dpipe_header_ipv4
;
328 match
.field_id
= DEVLINK_DPIPE_FIELD_IPV4_DST_IP
;
331 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
332 match
.header
= &devlink_dpipe_header_ipv6
;
333 match
.field_id
= DEVLINK_DPIPE_FIELD_IPV6_DST_IP
;
340 return devlink_dpipe_match_put(skb
, &match
);
344 mlxsw_sp_dpipe_table_host4_matches_dump(void *priv
, struct sk_buff
*skb
)
346 return mlxsw_sp_dpipe_table_host_matches_dump(skb
, AF_INET
);
350 mlxsw_sp_dpipe_table_host_actions_dump(void *priv
, struct sk_buff
*skb
)
352 struct devlink_dpipe_action action
= {0};
354 action
.type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
355 action
.header
= &devlink_dpipe_header_ethernet
;
356 action
.field_id
= DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC
;
358 return devlink_dpipe_action_put(skb
, &action
);
361 enum mlxsw_sp_dpipe_table_host_match
{
362 MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF
,
363 MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP
,
364 MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT
,
368 mlxsw_sp_dpipe_table_host_match_action_prepare(struct devlink_dpipe_match
*matches
,
369 struct devlink_dpipe_action
*action
,
372 struct devlink_dpipe_match
*match
;
374 match
= &matches
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF
];
375 match
->type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
376 match
->header
= &mlxsw_sp_dpipe_header_metadata
;
377 match
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
;
379 match
= &matches
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP
];
380 match
->type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
383 match
->header
= &devlink_dpipe_header_ipv4
;
384 match
->field_id
= DEVLINK_DPIPE_FIELD_IPV4_DST_IP
;
387 match
->header
= &devlink_dpipe_header_ipv6
;
388 match
->field_id
= DEVLINK_DPIPE_FIELD_IPV6_DST_IP
;
395 action
->type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
396 action
->header
= &devlink_dpipe_header_ethernet
;
397 action
->field_id
= DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC
;
401 mlxsw_sp_dpipe_table_host_entry_prepare(struct devlink_dpipe_entry
*entry
,
402 struct devlink_dpipe_value
*match_values
,
403 struct devlink_dpipe_match
*matches
,
404 struct devlink_dpipe_value
*action_value
,
405 struct devlink_dpipe_action
*action
,
408 struct devlink_dpipe_value
*match_value
;
409 struct devlink_dpipe_match
*match
;
411 entry
->match_values
= match_values
;
412 entry
->match_values_count
= MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT
;
414 entry
->action_values
= action_value
;
415 entry
->action_values_count
= 1;
417 match
= &matches
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF
];
418 match_value
= &match_values
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF
];
420 match_value
->match
= match
;
421 match_value
->value_size
= sizeof(u32
);
422 match_value
->value
= kmalloc(match_value
->value_size
, GFP_KERNEL
);
423 if (!match_value
->value
)
426 match
= &matches
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP
];
427 match_value
= &match_values
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP
];
429 match_value
->match
= match
;
432 match_value
->value_size
= sizeof(u32
);
435 match_value
->value_size
= sizeof(struct in6_addr
);
442 match_value
->value
= kmalloc(match_value
->value_size
, GFP_KERNEL
);
443 if (!match_value
->value
)
446 action_value
->action
= action
;
447 action_value
->value_size
= sizeof(u64
);
448 action_value
->value
= kmalloc(action_value
->value_size
, GFP_KERNEL
);
449 if (!action_value
->value
)
456 __mlxsw_sp_dpipe_table_host_entry_fill(struct devlink_dpipe_entry
*entry
,
457 struct mlxsw_sp_rif
*rif
,
458 unsigned char *ha
, void *dip
)
460 struct devlink_dpipe_value
*value
;
464 /* Set Match RIF index */
465 value
= &entry
->match_values
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF
];
467 rif_value
= value
->value
;
468 *rif_value
= mlxsw_sp_rif_index(rif
);
469 value
->mapping_value
= mlxsw_sp_rif_dev_ifindex(rif
);
470 value
->mapping_valid
= true;
473 value
= &entry
->match_values
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP
];
474 memcpy(value
->value
, dip
, value
->value_size
);
476 /* Set Action DMAC */
477 value
= entry
->action_values
;
478 ha_value
= value
->value
;
479 ether_addr_copy(ha_value
, ha
);
483 mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry
*entry
,
484 struct mlxsw_sp_neigh_entry
*neigh_entry
,
485 struct mlxsw_sp_rif
*rif
)
490 ha
= mlxsw_sp_neigh_entry_ha(neigh_entry
);
491 dip
= mlxsw_sp_neigh4_entry_dip(neigh_entry
);
492 __mlxsw_sp_dpipe_table_host_entry_fill(entry
, rif
, ha
, &dip
);
496 mlxsw_sp_dpipe_table_host6_entry_fill(struct devlink_dpipe_entry
*entry
,
497 struct mlxsw_sp_neigh_entry
*neigh_entry
,
498 struct mlxsw_sp_rif
*rif
)
500 struct in6_addr
*dip
;
503 ha
= mlxsw_sp_neigh_entry_ha(neigh_entry
);
504 dip
= mlxsw_sp_neigh6_entry_dip(neigh_entry
);
506 __mlxsw_sp_dpipe_table_host_entry_fill(entry
, rif
, ha
, dip
);
510 mlxsw_sp_dpipe_table_host_entry_fill(struct mlxsw_sp
*mlxsw_sp
,
511 struct devlink_dpipe_entry
*entry
,
512 struct mlxsw_sp_neigh_entry
*neigh_entry
,
513 struct mlxsw_sp_rif
*rif
,
520 mlxsw_sp_dpipe_table_host4_entry_fill(entry
, neigh_entry
, rif
);
523 mlxsw_sp_dpipe_table_host6_entry_fill(entry
, neigh_entry
, rif
);
530 err
= mlxsw_sp_neigh_counter_get(mlxsw_sp
, neigh_entry
,
533 entry
->counter_valid
= true;
537 mlxsw_sp_dpipe_table_host_entries_get(struct mlxsw_sp
*mlxsw_sp
,
538 struct devlink_dpipe_entry
*entry
,
539 bool counters_enabled
,
540 struct devlink_dpipe_dump_ctx
*dump_ctx
,
543 int rif_neigh_count
= 0;
544 int rif_neigh_skip
= 0;
550 mutex_lock(&mlxsw_sp
->router
->lock
);
552 rif_count
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
554 err
= devlink_dpipe_entry_ctx_prepare(dump_ctx
);
556 goto err_ctx_prepare
;
558 rif_neigh_skip
= rif_neigh_count
;
559 for (; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++) {
560 struct mlxsw_sp_rif
*rif
= mlxsw_sp_rif_by_index(mlxsw_sp
, i
);
561 struct mlxsw_sp_neigh_entry
*neigh_entry
;
567 mlxsw_sp_rif_neigh_for_each(neigh_entry
, rif
) {
568 int neigh_type
= mlxsw_sp_neigh_entry_type(neigh_entry
);
570 if (neigh_type
!= type
)
573 if (neigh_type
== AF_INET6
&&
574 mlxsw_sp_neigh_ipv6_ignore(neigh_entry
))
577 if (rif_neigh_count
< rif_neigh_skip
)
580 mlxsw_sp_dpipe_table_host_entry_fill(mlxsw_sp
, entry
,
583 entry
->index
= neigh_count
;
584 err
= devlink_dpipe_entry_ctx_append(dump_ctx
, entry
);
586 if (err
== -EMSGSIZE
) {
588 goto err_entry_append
;
592 goto err_entry_append
;
602 devlink_dpipe_entry_ctx_close(dump_ctx
);
606 mutex_unlock(&mlxsw_sp
->router
->lock
);
611 mutex_unlock(&mlxsw_sp
->router
->lock
);
616 mlxsw_sp_dpipe_table_host_entries_dump(struct mlxsw_sp
*mlxsw_sp
,
617 bool counters_enabled
,
618 struct devlink_dpipe_dump_ctx
*dump_ctx
,
621 struct devlink_dpipe_value match_values
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT
];
622 struct devlink_dpipe_match matches
[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT
];
623 struct devlink_dpipe_value action_value
;
624 struct devlink_dpipe_action action
= {0};
625 struct devlink_dpipe_entry entry
= {0};
628 memset(matches
, 0, MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT
*
630 memset(match_values
, 0, MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT
*
631 sizeof(match_values
[0]));
632 memset(&action_value
, 0, sizeof(action_value
));
634 mlxsw_sp_dpipe_table_host_match_action_prepare(matches
, &action
, type
);
635 err
= mlxsw_sp_dpipe_table_host_entry_prepare(&entry
, match_values
,
636 matches
, &action_value
,
641 err
= mlxsw_sp_dpipe_table_host_entries_get(mlxsw_sp
, &entry
,
642 counters_enabled
, dump_ctx
,
645 devlink_dpipe_entry_clear(&entry
);
650 mlxsw_sp_dpipe_table_host4_entries_dump(void *priv
, bool counters_enabled
,
651 struct devlink_dpipe_dump_ctx
*dump_ctx
)
653 struct mlxsw_sp
*mlxsw_sp
= priv
;
655 return mlxsw_sp_dpipe_table_host_entries_dump(mlxsw_sp
,
661 mlxsw_sp_dpipe_table_host_counters_update(struct mlxsw_sp
*mlxsw_sp
,
662 bool enable
, int type
)
666 mutex_lock(&mlxsw_sp
->router
->lock
);
667 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++) {
668 struct mlxsw_sp_rif
*rif
= mlxsw_sp_rif_by_index(mlxsw_sp
, i
);
669 struct mlxsw_sp_neigh_entry
*neigh_entry
;
673 mlxsw_sp_rif_neigh_for_each(neigh_entry
, rif
) {
674 int neigh_type
= mlxsw_sp_neigh_entry_type(neigh_entry
);
676 if (neigh_type
!= type
)
679 if (neigh_type
== AF_INET6
&&
680 mlxsw_sp_neigh_ipv6_ignore(neigh_entry
))
683 mlxsw_sp_neigh_entry_counter_update(mlxsw_sp
,
688 mutex_unlock(&mlxsw_sp
->router
->lock
);
691 static int mlxsw_sp_dpipe_table_host4_counters_update(void *priv
, bool enable
)
693 struct mlxsw_sp
*mlxsw_sp
= priv
;
695 mlxsw_sp_dpipe_table_host_counters_update(mlxsw_sp
, enable
, AF_INET
);
700 mlxsw_sp_dpipe_table_host_size_get(struct mlxsw_sp
*mlxsw_sp
, int type
)
705 mutex_lock(&mlxsw_sp
->router
->lock
);
706 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++) {
707 struct mlxsw_sp_rif
*rif
= mlxsw_sp_rif_by_index(mlxsw_sp
, i
);
708 struct mlxsw_sp_neigh_entry
*neigh_entry
;
712 mlxsw_sp_rif_neigh_for_each(neigh_entry
, rif
) {
713 int neigh_type
= mlxsw_sp_neigh_entry_type(neigh_entry
);
715 if (neigh_type
!= type
)
718 if (neigh_type
== AF_INET6
&&
719 mlxsw_sp_neigh_ipv6_ignore(neigh_entry
))
725 mutex_unlock(&mlxsw_sp
->router
->lock
);
730 static u64
mlxsw_sp_dpipe_table_host4_size_get(void *priv
)
732 struct mlxsw_sp
*mlxsw_sp
= priv
;
734 return mlxsw_sp_dpipe_table_host_size_get(mlxsw_sp
, AF_INET
);
737 static struct devlink_dpipe_table_ops mlxsw_sp_host4_ops
= {
738 .matches_dump
= mlxsw_sp_dpipe_table_host4_matches_dump
,
739 .actions_dump
= mlxsw_sp_dpipe_table_host_actions_dump
,
740 .entries_dump
= mlxsw_sp_dpipe_table_host4_entries_dump
,
741 .counters_set_update
= mlxsw_sp_dpipe_table_host4_counters_update
,
742 .size_get
= mlxsw_sp_dpipe_table_host4_size_get
,
745 #define MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST4 1
747 static int mlxsw_sp_dpipe_host4_table_init(struct mlxsw_sp
*mlxsw_sp
)
749 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
752 err
= devlink_dpipe_table_register(devlink
,
753 MLXSW_SP_DPIPE_TABLE_NAME_HOST4
,
759 err
= devlink_dpipe_table_resource_set(devlink
,
760 MLXSW_SP_DPIPE_TABLE_NAME_HOST4
,
761 MLXSW_SP_RESOURCE_KVD_HASH_SINGLE
,
762 MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST4
);
764 goto err_resource_set
;
769 devlink_dpipe_table_unregister(devlink
,
770 MLXSW_SP_DPIPE_TABLE_NAME_HOST4
);
774 static void mlxsw_sp_dpipe_host4_table_fini(struct mlxsw_sp
*mlxsw_sp
)
776 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
778 devlink_dpipe_table_unregister(devlink
,
779 MLXSW_SP_DPIPE_TABLE_NAME_HOST4
);
783 mlxsw_sp_dpipe_table_host6_matches_dump(void *priv
, struct sk_buff
*skb
)
785 return mlxsw_sp_dpipe_table_host_matches_dump(skb
, AF_INET6
);
789 mlxsw_sp_dpipe_table_host6_entries_dump(void *priv
, bool counters_enabled
,
790 struct devlink_dpipe_dump_ctx
*dump_ctx
)
792 struct mlxsw_sp
*mlxsw_sp
= priv
;
794 return mlxsw_sp_dpipe_table_host_entries_dump(mlxsw_sp
,
799 static int mlxsw_sp_dpipe_table_host6_counters_update(void *priv
, bool enable
)
801 struct mlxsw_sp
*mlxsw_sp
= priv
;
803 mlxsw_sp_dpipe_table_host_counters_update(mlxsw_sp
, enable
, AF_INET6
);
807 static u64
mlxsw_sp_dpipe_table_host6_size_get(void *priv
)
809 struct mlxsw_sp
*mlxsw_sp
= priv
;
811 return mlxsw_sp_dpipe_table_host_size_get(mlxsw_sp
, AF_INET6
);
814 static struct devlink_dpipe_table_ops mlxsw_sp_host6_ops
= {
815 .matches_dump
= mlxsw_sp_dpipe_table_host6_matches_dump
,
816 .actions_dump
= mlxsw_sp_dpipe_table_host_actions_dump
,
817 .entries_dump
= mlxsw_sp_dpipe_table_host6_entries_dump
,
818 .counters_set_update
= mlxsw_sp_dpipe_table_host6_counters_update
,
819 .size_get
= mlxsw_sp_dpipe_table_host6_size_get
,
822 #define MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST6 2
824 static int mlxsw_sp_dpipe_host6_table_init(struct mlxsw_sp
*mlxsw_sp
)
826 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
829 err
= devlink_dpipe_table_register(devlink
,
830 MLXSW_SP_DPIPE_TABLE_NAME_HOST6
,
836 err
= devlink_dpipe_table_resource_set(devlink
,
837 MLXSW_SP_DPIPE_TABLE_NAME_HOST6
,
838 MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE
,
839 MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST6
);
841 goto err_resource_set
;
846 devlink_dpipe_table_unregister(devlink
,
847 MLXSW_SP_DPIPE_TABLE_NAME_HOST6
);
851 static void mlxsw_sp_dpipe_host6_table_fini(struct mlxsw_sp
*mlxsw_sp
)
853 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
855 devlink_dpipe_table_unregister(devlink
,
856 MLXSW_SP_DPIPE_TABLE_NAME_HOST6
);
859 static int mlxsw_sp_dpipe_table_adj_matches_dump(void *priv
,
862 struct devlink_dpipe_match match
= {0};
865 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
866 match
.header
= &mlxsw_sp_dpipe_header_metadata
;
867 match
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_INDEX
;
869 err
= devlink_dpipe_match_put(skb
, &match
);
873 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
874 match
.header
= &mlxsw_sp_dpipe_header_metadata
;
875 match
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_SIZE
;
877 err
= devlink_dpipe_match_put(skb
, &match
);
881 match
.type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
882 match
.header
= &mlxsw_sp_dpipe_header_metadata
;
883 match
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_HASH_INDEX
;
885 return devlink_dpipe_match_put(skb
, &match
);
888 static int mlxsw_sp_dpipe_table_adj_actions_dump(void *priv
,
891 struct devlink_dpipe_action action
= {0};
894 action
.type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
895 action
.header
= &devlink_dpipe_header_ethernet
;
896 action
.field_id
= DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC
;
898 err
= devlink_dpipe_action_put(skb
, &action
);
902 action
.type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
903 action
.header
= &mlxsw_sp_dpipe_header_metadata
;
904 action
.field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
;
906 return devlink_dpipe_action_put(skb
, &action
);
909 static u64
mlxsw_sp_dpipe_table_adj_size(struct mlxsw_sp
*mlxsw_sp
)
911 struct mlxsw_sp_nexthop
*nh
;
914 mlxsw_sp_nexthop_for_each(nh
, mlxsw_sp
->router
)
915 if (mlxsw_sp_nexthop_offload(nh
) &&
916 !mlxsw_sp_nexthop_group_has_ipip(nh
))
921 enum mlxsw_sp_dpipe_table_adj_match
{
922 MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX
,
923 MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE
,
924 MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX
,
925 MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT
,
928 enum mlxsw_sp_dpipe_table_adj_action
{
929 MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC
,
930 MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT
,
931 MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT
,
935 mlxsw_sp_dpipe_table_adj_match_action_prepare(struct devlink_dpipe_match
*matches
,
936 struct devlink_dpipe_action
*actions
)
938 struct devlink_dpipe_action
*action
;
939 struct devlink_dpipe_match
*match
;
941 match
= &matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX
];
942 match
->type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
943 match
->header
= &mlxsw_sp_dpipe_header_metadata
;
944 match
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_INDEX
;
946 match
= &matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE
];
947 match
->type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
948 match
->header
= &mlxsw_sp_dpipe_header_metadata
;
949 match
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_SIZE
;
951 match
= &matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX
];
952 match
->type
= DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT
;
953 match
->header
= &mlxsw_sp_dpipe_header_metadata
;
954 match
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_HASH_INDEX
;
956 action
= &actions
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC
];
957 action
->type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
958 action
->header
= &devlink_dpipe_header_ethernet
;
959 action
->field_id
= DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC
;
961 action
= &actions
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT
];
962 action
->type
= DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY
;
963 action
->header
= &mlxsw_sp_dpipe_header_metadata
;
964 action
->field_id
= MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT
;
968 mlxsw_sp_dpipe_table_adj_entry_prepare(struct devlink_dpipe_entry
*entry
,
969 struct devlink_dpipe_value
*match_values
,
970 struct devlink_dpipe_match
*matches
,
971 struct devlink_dpipe_value
*action_values
,
972 struct devlink_dpipe_action
*actions
)
973 { struct devlink_dpipe_value
*action_value
;
974 struct devlink_dpipe_value
*match_value
;
975 struct devlink_dpipe_action
*action
;
976 struct devlink_dpipe_match
*match
;
978 entry
->match_values
= match_values
;
979 entry
->match_values_count
= MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT
;
981 entry
->action_values
= action_values
;
982 entry
->action_values_count
= MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT
;
984 match
= &matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX
];
985 match_value
= &match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX
];
987 match_value
->match
= match
;
988 match_value
->value_size
= sizeof(u32
);
989 match_value
->value
= kmalloc(match_value
->value_size
, GFP_KERNEL
);
990 if (!match_value
->value
)
993 match
= &matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE
];
994 match_value
= &match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE
];
996 match_value
->match
= match
;
997 match_value
->value_size
= sizeof(u32
);
998 match_value
->value
= kmalloc(match_value
->value_size
, GFP_KERNEL
);
999 if (!match_value
->value
)
1002 match
= &matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX
];
1003 match_value
= &match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX
];
1005 match_value
->match
= match
;
1006 match_value
->value_size
= sizeof(u32
);
1007 match_value
->value
= kmalloc(match_value
->value_size
, GFP_KERNEL
);
1008 if (!match_value
->value
)
1011 action
= &actions
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC
];
1012 action_value
= &action_values
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC
];
1014 action_value
->action
= action
;
1015 action_value
->value_size
= sizeof(u64
);
1016 action_value
->value
= kmalloc(action_value
->value_size
, GFP_KERNEL
);
1017 if (!action_value
->value
)
1020 action
= &actions
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT
];
1021 action_value
= &action_values
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT
];
1023 action_value
->action
= action
;
1024 action_value
->value_size
= sizeof(u32
);
1025 action_value
->value
= kmalloc(action_value
->value_size
, GFP_KERNEL
);
1026 if (!action_value
->value
)
1033 __mlxsw_sp_dpipe_table_adj_entry_fill(struct devlink_dpipe_entry
*entry
,
1034 u32 adj_index
, u32 adj_size
,
1035 u32 adj_hash_index
, unsigned char *ha
,
1036 struct mlxsw_sp_rif
*rif
)
1038 struct devlink_dpipe_value
*value
;
1042 value
= &entry
->match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX
];
1043 p_index
= value
->value
;
1044 *p_index
= adj_index
;
1046 value
= &entry
->match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE
];
1047 p_index
= value
->value
;
1048 *p_index
= adj_size
;
1050 value
= &entry
->match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX
];
1051 p_index
= value
->value
;
1052 *p_index
= adj_hash_index
;
1054 value
= &entry
->action_values
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC
];
1055 ether_addr_copy(value
->value
, ha
);
1057 value
= &entry
->action_values
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT
];
1058 p_rif_value
= value
->value
;
1059 *p_rif_value
= mlxsw_sp_rif_index(rif
);
1060 value
->mapping_value
= mlxsw_sp_rif_dev_ifindex(rif
);
1061 value
->mapping_valid
= true;
1064 static void mlxsw_sp_dpipe_table_adj_entry_fill(struct mlxsw_sp
*mlxsw_sp
,
1065 struct mlxsw_sp_nexthop
*nh
,
1066 struct devlink_dpipe_entry
*entry
)
1068 struct mlxsw_sp_rif
*rif
= mlxsw_sp_nexthop_rif(nh
);
1069 unsigned char *ha
= mlxsw_sp_nexthop_ha(nh
);
1070 u32 adj_hash_index
= 0;
1075 mlxsw_sp_nexthop_indexes(nh
, &adj_index
, &adj_size
, &adj_hash_index
);
1076 __mlxsw_sp_dpipe_table_adj_entry_fill(entry
, adj_index
, adj_size
,
1077 adj_hash_index
, ha
, rif
);
1078 err
= mlxsw_sp_nexthop_counter_get(mlxsw_sp
, nh
, &entry
->counter
);
1080 entry
->counter_valid
= true;
1084 mlxsw_sp_dpipe_table_adj_entries_get(struct mlxsw_sp
*mlxsw_sp
,
1085 struct devlink_dpipe_entry
*entry
,
1086 bool counters_enabled
,
1087 struct devlink_dpipe_dump_ctx
*dump_ctx
)
1089 struct mlxsw_sp_nexthop
*nh
;
1090 int entry_index
= 0;
1097 mutex_lock(&mlxsw_sp
->router
->lock
);
1098 nh_count_max
= mlxsw_sp_dpipe_table_adj_size(mlxsw_sp
);
1100 err
= devlink_dpipe_entry_ctx_prepare(dump_ctx
);
1102 goto err_ctx_prepare
;
1106 mlxsw_sp_nexthop_for_each(nh
, mlxsw_sp
->router
) {
1107 if (!mlxsw_sp_nexthop_offload(nh
) ||
1108 mlxsw_sp_nexthop_group_has_ipip(nh
))
1111 if (nh_count
< nh_skip
)
1114 mlxsw_sp_dpipe_table_adj_entry_fill(mlxsw_sp
, nh
, entry
);
1115 entry
->index
= entry_index
;
1116 err
= devlink_dpipe_entry_ctx_append(dump_ctx
, entry
);
1118 if (err
== -EMSGSIZE
) {
1120 goto err_entry_append
;
1123 goto err_entry_append
;
1131 devlink_dpipe_entry_ctx_close(dump_ctx
);
1132 if (nh_count
!= nh_count_max
)
1134 mutex_unlock(&mlxsw_sp
->router
->lock
);
1140 mutex_unlock(&mlxsw_sp
->router
->lock
);
1145 mlxsw_sp_dpipe_table_adj_entries_dump(void *priv
, bool counters_enabled
,
1146 struct devlink_dpipe_dump_ctx
*dump_ctx
)
1148 struct devlink_dpipe_value action_values
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT
];
1149 struct devlink_dpipe_value match_values
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT
];
1150 struct devlink_dpipe_action actions
[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT
];
1151 struct devlink_dpipe_match matches
[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT
];
1152 struct devlink_dpipe_entry entry
= {0};
1153 struct mlxsw_sp
*mlxsw_sp
= priv
;
1156 memset(matches
, 0, MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT
*
1157 sizeof(matches
[0]));
1158 memset(match_values
, 0, MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT
*
1159 sizeof(match_values
[0]));
1160 memset(actions
, 0, MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT
*
1161 sizeof(actions
[0]));
1162 memset(action_values
, 0, MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT
*
1163 sizeof(action_values
[0]));
1165 mlxsw_sp_dpipe_table_adj_match_action_prepare(matches
, actions
);
1166 err
= mlxsw_sp_dpipe_table_adj_entry_prepare(&entry
,
1167 match_values
, matches
,
1168 action_values
, actions
);
1172 err
= mlxsw_sp_dpipe_table_adj_entries_get(mlxsw_sp
, &entry
,
1173 counters_enabled
, dump_ctx
);
1175 devlink_dpipe_entry_clear(&entry
);
1179 static int mlxsw_sp_dpipe_table_adj_counters_update(void *priv
, bool enable
)
1181 struct mlxsw_sp
*mlxsw_sp
= priv
;
1182 struct mlxsw_sp_nexthop
*nh
;
1183 u32 adj_hash_index
= 0;
1187 mlxsw_sp_nexthop_for_each(nh
, mlxsw_sp
->router
) {
1188 if (!mlxsw_sp_nexthop_offload(nh
) ||
1189 mlxsw_sp_nexthop_group_has_ipip(nh
))
1192 mlxsw_sp_nexthop_indexes(nh
, &adj_index
, &adj_size
,
1195 mlxsw_sp_nexthop_counter_alloc(mlxsw_sp
, nh
);
1197 mlxsw_sp_nexthop_counter_free(mlxsw_sp
, nh
);
1198 mlxsw_sp_nexthop_update(mlxsw_sp
,
1199 adj_index
+ adj_hash_index
, nh
);
1205 mlxsw_sp_dpipe_table_adj_size_get(void *priv
)
1207 struct mlxsw_sp
*mlxsw_sp
= priv
;
1210 mutex_lock(&mlxsw_sp
->router
->lock
);
1211 size
= mlxsw_sp_dpipe_table_adj_size(mlxsw_sp
);
1212 mutex_unlock(&mlxsw_sp
->router
->lock
);
1217 static struct devlink_dpipe_table_ops mlxsw_sp_dpipe_table_adj_ops
= {
1218 .matches_dump
= mlxsw_sp_dpipe_table_adj_matches_dump
,
1219 .actions_dump
= mlxsw_sp_dpipe_table_adj_actions_dump
,
1220 .entries_dump
= mlxsw_sp_dpipe_table_adj_entries_dump
,
1221 .counters_set_update
= mlxsw_sp_dpipe_table_adj_counters_update
,
1222 .size_get
= mlxsw_sp_dpipe_table_adj_size_get
,
1225 #define MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_ADJ 1
1227 static int mlxsw_sp_dpipe_adj_table_init(struct mlxsw_sp
*mlxsw_sp
)
1229 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
1232 err
= devlink_dpipe_table_register(devlink
,
1233 MLXSW_SP_DPIPE_TABLE_NAME_ADJ
,
1234 &mlxsw_sp_dpipe_table_adj_ops
,
1239 err
= devlink_dpipe_table_resource_set(devlink
,
1240 MLXSW_SP_DPIPE_TABLE_NAME_ADJ
,
1241 MLXSW_SP_RESOURCE_KVD_LINEAR
,
1242 MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_ADJ
);
1244 goto err_resource_set
;
1249 devlink_dpipe_table_unregister(devlink
,
1250 MLXSW_SP_DPIPE_TABLE_NAME_ADJ
);
1254 static void mlxsw_sp_dpipe_adj_table_fini(struct mlxsw_sp
*mlxsw_sp
)
1256 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
1258 devlink_dpipe_table_unregister(devlink
,
1259 MLXSW_SP_DPIPE_TABLE_NAME_ADJ
);
1262 int mlxsw_sp_dpipe_init(struct mlxsw_sp
*mlxsw_sp
)
1264 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
1267 err
= devlink_dpipe_headers_register(devlink
,
1268 &mlxsw_sp_dpipe_headers
);
1271 err
= mlxsw_sp_dpipe_erif_table_init(mlxsw_sp
);
1273 goto err_erif_table_init
;
1275 err
= mlxsw_sp_dpipe_host4_table_init(mlxsw_sp
);
1277 goto err_host4_table_init
;
1279 err
= mlxsw_sp_dpipe_host6_table_init(mlxsw_sp
);
1281 goto err_host6_table_init
;
1283 err
= mlxsw_sp_dpipe_adj_table_init(mlxsw_sp
);
1285 goto err_adj_table_init
;
1289 mlxsw_sp_dpipe_host6_table_fini(mlxsw_sp
);
1290 err_host6_table_init
:
1291 mlxsw_sp_dpipe_host4_table_fini(mlxsw_sp
);
1292 err_host4_table_init
:
1293 mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp
);
1294 err_erif_table_init
:
1295 devlink_dpipe_headers_unregister(priv_to_devlink(mlxsw_sp
->core
));
1299 void mlxsw_sp_dpipe_fini(struct mlxsw_sp
*mlxsw_sp
)
1301 struct devlink
*devlink
= priv_to_devlink(mlxsw_sp
->core
);
1303 mlxsw_sp_dpipe_adj_table_fini(mlxsw_sp
);
1304 mlxsw_sp_dpipe_host6_table_fini(mlxsw_sp
);
1305 mlxsw_sp_dpipe_host4_table_fini(mlxsw_sp
);
1306 mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp
);
1307 devlink_dpipe_headers_unregister(devlink
);