1323 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */3 4#include <linux/kernel.h>5#include <linux/mutex.h>6#include <net/devlink.h>7 8#include "spectrum.h"9#include "spectrum_dpipe.h"10#include "spectrum_router.h"11 12enum 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,19};20 21static struct devlink_dpipe_field mlxsw_sp_dpipe_fields_metadata[] = {22 {23 .name = "erif_port",24 .id = MLXSW_SP_DPIPE_FIELD_METADATA_ERIF_PORT,25 .bitwidth = 32,26 .mapping_type = DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX,27 },28 {29 .name = "l3_forward",30 .id = MLXSW_SP_DPIPE_FIELD_METADATA_L3_FORWARD,31 .bitwidth = 1,32 },33 {34 .name = "l3_drop",35 .id = MLXSW_SP_DPIPE_FIELD_METADATA_L3_DROP,36 .bitwidth = 1,37 },38 {39 .name = "adj_index",40 .id = MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_INDEX,41 .bitwidth = 32,42 },43 {44 .name = "adj_size",45 .id = MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_SIZE,46 .bitwidth = 32,47 },48 {49 .name = "adj_hash_index",50 .id = MLXSW_SP_DPIPE_FIELD_METADATA_ADJ_HASH_INDEX,51 .bitwidth = 32,52 },53};54 55enum mlxsw_sp_dpipe_header_id {56 MLXSW_SP_DPIPE_HEADER_METADATA,57};58 59static struct devlink_dpipe_header mlxsw_sp_dpipe_header_metadata = {60 .name = "mlxsw_meta",61 .id = MLXSW_SP_DPIPE_HEADER_METADATA,62 .fields = mlxsw_sp_dpipe_fields_metadata,63 .fields_count = ARRAY_SIZE(mlxsw_sp_dpipe_fields_metadata),64};65 66static 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,71};72 73static struct devlink_dpipe_headers mlxsw_sp_dpipe_headers = {74 .headers = mlxsw_dpipe_headers,75 .headers_count = ARRAY_SIZE(mlxsw_dpipe_headers),76};77 78static int mlxsw_sp_dpipe_table_erif_actions_dump(void *priv,79 struct sk_buff *skb)80{81 struct devlink_dpipe_action action = {0};82 int err;83 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;87 88 err = devlink_dpipe_action_put(skb, &action);89 if (err)90 return err;91 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;95 96 return devlink_dpipe_action_put(skb, &action);97}98 99static int mlxsw_sp_dpipe_table_erif_matches_dump(void *priv,100 struct sk_buff *skb)101{102 struct devlink_dpipe_match match = {0};103 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;107 108 return devlink_dpipe_match_put(skb, &match);109}110 111static void112mlxsw_sp_erif_match_action_prepare(struct devlink_dpipe_match *match,113 struct devlink_dpipe_action *action)114{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;118 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;122}123 124static 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)129{130 entry->match_values = match_value;131 entry->match_values_count = 1;132 133 entry->action_values = action_value;134 entry->action_values_count = 1;135 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)140 return -ENOMEM;141 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;147 return 0;148 149err_action_alloc:150 kfree(match_value->value);151 return -ENOMEM;152}153 154static 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)158{159 u32 *action_value;160 u32 *rif_value;161 u64 cnt;162 int err;163 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;169 170 /* Set Action Forwarding */171 action_value = entry->action_values->value;172 *action_value = 1;173 174 entry->counter_valid = false;175 entry->counter = 0;176 entry->index = mlxsw_sp_rif_index(rif);177 178 if (!counters_enabled)179 return 0;180 181 err = mlxsw_sp_rif_counter_value_get(mlxsw_sp, rif,182 MLXSW_SP_RIF_COUNTER_EGRESS,183 &cnt);184 if (!err) {185 entry->counter = cnt;186 entry->counter_valid = true;187 }188 return 0;189}190 191static int192mlxsw_sp_dpipe_table_erif_entries_dump(void *priv, bool counters_enabled,193 struct devlink_dpipe_dump_ctx *dump_ctx)194{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;201 int i, j;202 int err;203 204 memset(&match_value, 0, sizeof(match_value));205 memset(&action_value, 0, sizeof(action_value));206 207 mlxsw_sp_erif_match_action_prepare(&match, &action);208 err = mlxsw_sp_erif_entry_prepare(&entry, &match_value, &match,209 &action_value, &action);210 if (err)211 return err;212 213 rif_count = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);214 mutex_lock(&mlxsw_sp->router->lock);215 i = 0;216start_again:217 err = devlink_dpipe_entry_ctx_prepare(dump_ctx);218 if (err)219 goto err_ctx_prepare;220 j = 0;221 for (; i < rif_count; i++) {222 struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);223 224 if (!rif || !mlxsw_sp_rif_has_dev(rif))225 continue;226 err = mlxsw_sp_erif_entry_get(mlxsw_sp, &entry, rif,227 counters_enabled);228 if (err)229 goto err_entry_get;230 err = devlink_dpipe_entry_ctx_append(dump_ctx, &entry);231 if (err) {232 if (err == -EMSGSIZE) {233 if (!j)234 goto err_entry_append;235 break;236 }237 goto err_entry_append;238 }239 j++;240 }241 242 devlink_dpipe_entry_ctx_close(dump_ctx);243 if (i != rif_count)244 goto start_again;245 mutex_unlock(&mlxsw_sp->router->lock);246 247 devlink_dpipe_entry_clear(&entry);248 return 0;249err_entry_append:250err_entry_get:251err_ctx_prepare:252 mutex_unlock(&mlxsw_sp->router->lock);253 devlink_dpipe_entry_clear(&entry);254 return err;255}256 257static int mlxsw_sp_dpipe_table_erif_counters_update(void *priv, bool enable)258{259 struct mlxsw_sp *mlxsw_sp = priv;260 int i;261 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);265 266 if (!rif)267 continue;268 if (enable)269 mlxsw_sp_rif_counter_alloc(rif,270 MLXSW_SP_RIF_COUNTER_EGRESS);271 else272 mlxsw_sp_rif_counter_free(rif,273 MLXSW_SP_RIF_COUNTER_EGRESS);274 }275 mutex_unlock(&mlxsw_sp->router->lock);276 return 0;277}278 279static u64 mlxsw_sp_dpipe_table_erif_size_get(void *priv)280{281 struct mlxsw_sp *mlxsw_sp = priv;282 283 return MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);284}285 286static const 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,292};293 294static int mlxsw_sp_dpipe_erif_table_init(struct mlxsw_sp *mlxsw_sp)295{296 struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);297 298 return devl_dpipe_table_register(devlink,299 MLXSW_SP_DPIPE_TABLE_NAME_ERIF,300 &mlxsw_sp_erif_ops,301 mlxsw_sp, false);302}303 304static void mlxsw_sp_dpipe_erif_table_fini(struct mlxsw_sp *mlxsw_sp)305{306 struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);307 308 devl_dpipe_table_unregister(devlink, MLXSW_SP_DPIPE_TABLE_NAME_ERIF);309}310 311static int mlxsw_sp_dpipe_table_host_matches_dump(struct sk_buff *skb, int type)312{313 struct devlink_dpipe_match match = {0};314 int err;315 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;319 320 err = devlink_dpipe_match_put(skb, &match);321 if (err)322 return err;323 324 switch (type) {325 case AF_INET: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;329 break;330 case AF_INET6: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;334 break;335 default:336 WARN_ON(1);337 return -EINVAL;338 }339 340 return devlink_dpipe_match_put(skb, &match);341}342 343static int344mlxsw_sp_dpipe_table_host4_matches_dump(void *priv, struct sk_buff *skb)345{346 return mlxsw_sp_dpipe_table_host_matches_dump(skb, AF_INET);347}348 349static int350mlxsw_sp_dpipe_table_host_actions_dump(void *priv, struct sk_buff *skb)351{352 struct devlink_dpipe_action action = {0};353 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;357 358 return devlink_dpipe_action_put(skb, &action);359}360 361enum 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,365};366 367static void368mlxsw_sp_dpipe_table_host_match_action_prepare(struct devlink_dpipe_match *matches,369 struct devlink_dpipe_action *action,370 int type)371{372 struct devlink_dpipe_match *match;373 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;378 379 match = &matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];380 match->type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;381 switch (type) {382 case AF_INET:383 match->header = &devlink_dpipe_header_ipv4;384 match->field_id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP;385 break;386 case AF_INET6:387 match->header = &devlink_dpipe_header_ipv6;388 match->field_id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP;389 break;390 default:391 WARN_ON(1);392 return;393 }394 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;398}399 400static int401mlxsw_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,406 int type)407{408 struct devlink_dpipe_value *match_value;409 struct devlink_dpipe_match *match;410 411 entry->match_values = match_values;412 entry->match_values_count = MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT;413 414 entry->action_values = action_value;415 entry->action_values_count = 1;416 417 match = &matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF];418 match_value = &match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF];419 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)424 return -ENOMEM;425 426 match = &matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];427 match_value = &match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];428 429 match_value->match = match;430 switch (type) {431 case AF_INET:432 match_value->value_size = sizeof(u32);433 break;434 case AF_INET6:435 match_value->value_size = sizeof(struct in6_addr);436 break;437 default:438 WARN_ON(1);439 return -EINVAL;440 }441 442 match_value->value = kmalloc(match_value->value_size, GFP_KERNEL);443 if (!match_value->value)444 return -ENOMEM;445 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)450 return -ENOMEM;451 452 return 0;453}454 455static void456__mlxsw_sp_dpipe_table_host_entry_fill(struct devlink_dpipe_entry *entry,457 struct mlxsw_sp_rif *rif,458 unsigned char *ha, void *dip)459{460 struct devlink_dpipe_value *value;461 u32 *rif_value;462 u8 *ha_value;463 464 /* Set Match RIF index */465 value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_RIF];466 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;471 472 /* Set Match DIP */473 value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];474 memcpy(value->value, dip, value->value_size);475 476 /* Set Action DMAC */477 value = entry->action_values;478 ha_value = value->value;479 ether_addr_copy(ha_value, ha);480}481 482static void483mlxsw_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)486{487 unsigned char *ha;488 u32 dip;489 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);493}494 495static void496mlxsw_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)499{500 struct in6_addr *dip;501 unsigned char *ha;502 503 ha = mlxsw_sp_neigh_entry_ha(neigh_entry);504 dip = mlxsw_sp_neigh6_entry_dip(neigh_entry);505 506 __mlxsw_sp_dpipe_table_host_entry_fill(entry, rif, ha, dip);507}508 509static void510mlxsw_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,514 int type)515{516 int err;517 518 switch (type) {519 case AF_INET:520 mlxsw_sp_dpipe_table_host4_entry_fill(entry, neigh_entry, rif);521 break;522 case AF_INET6:523 mlxsw_sp_dpipe_table_host6_entry_fill(entry, neigh_entry, rif);524 break;525 default:526 WARN_ON(1);527 return;528 }529 530 err = mlxsw_sp_neigh_counter_get(mlxsw_sp, neigh_entry,531 &entry->counter);532 if (!err)533 entry->counter_valid = true;534}535 536static int537mlxsw_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,541 int type)542{543 int rif_neigh_count = 0;544 int rif_neigh_skip = 0;545 int neigh_count = 0;546 int rif_count;547 int i, j;548 int err;549 550 mutex_lock(&mlxsw_sp->router->lock);551 i = 0;552 rif_count = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);553start_again:554 err = devlink_dpipe_entry_ctx_prepare(dump_ctx);555 if (err)556 goto err_ctx_prepare;557 j = 0;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;562 563 if (!rif)564 continue;565 566 rif_neigh_count = 0;567 mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {568 int neigh_type = mlxsw_sp_neigh_entry_type(neigh_entry);569 570 if (neigh_type != type)571 continue;572 573 if (neigh_type == AF_INET6 &&574 mlxsw_sp_neigh_ipv6_ignore(neigh_entry))575 continue;576 577 if (rif_neigh_count < rif_neigh_skip)578 goto skip;579 580 mlxsw_sp_dpipe_table_host_entry_fill(mlxsw_sp, entry,581 neigh_entry, rif,582 type);583 entry->index = neigh_count;584 err = devlink_dpipe_entry_ctx_append(dump_ctx, entry);585 if (err) {586 if (err == -EMSGSIZE) {587 if (!j)588 goto err_entry_append;589 else590 goto out;591 }592 goto err_entry_append;593 }594 neigh_count++;595 j++;596skip:597 rif_neigh_count++;598 }599 rif_neigh_skip = 0;600 }601out:602 devlink_dpipe_entry_ctx_close(dump_ctx);603 if (i != rif_count)604 goto start_again;605 606 mutex_unlock(&mlxsw_sp->router->lock);607 return 0;608 609err_ctx_prepare:610err_entry_append:611 mutex_unlock(&mlxsw_sp->router->lock);612 return err;613}614 615static int616mlxsw_sp_dpipe_table_host_entries_dump(struct mlxsw_sp *mlxsw_sp,617 bool counters_enabled,618 struct devlink_dpipe_dump_ctx *dump_ctx,619 int type)620{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};626 int err;627 628 memset(matches, 0, MLXSW_SP_DPIPE_TABLE_HOST_MATCH_COUNT *629 sizeof(matches[0]));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));633 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,637 &action, type);638 if (err)639 goto out;640 641 err = mlxsw_sp_dpipe_table_host_entries_get(mlxsw_sp, &entry,642 counters_enabled, dump_ctx,643 type);644out:645 devlink_dpipe_entry_clear(&entry);646 return err;647}648 649static int650mlxsw_sp_dpipe_table_host4_entries_dump(void *priv, bool counters_enabled,651 struct devlink_dpipe_dump_ctx *dump_ctx)652{653 struct mlxsw_sp *mlxsw_sp = priv;654 655 return mlxsw_sp_dpipe_table_host_entries_dump(mlxsw_sp,656 counters_enabled,657 dump_ctx, AF_INET);658}659 660static void661mlxsw_sp_dpipe_table_host_counters_update(struct mlxsw_sp *mlxsw_sp,662 bool enable, int type)663{664 int i;665 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;670 671 if (!rif)672 continue;673 mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {674 int neigh_type = mlxsw_sp_neigh_entry_type(neigh_entry);675 676 if (neigh_type != type)677 continue;678 679 if (neigh_type == AF_INET6 &&680 mlxsw_sp_neigh_ipv6_ignore(neigh_entry))681 continue;682 683 mlxsw_sp_neigh_entry_counter_update(mlxsw_sp,684 neigh_entry,685 enable);686 }687 }688 mutex_unlock(&mlxsw_sp->router->lock);689}690 691static int mlxsw_sp_dpipe_table_host4_counters_update(void *priv, bool enable)692{693 struct mlxsw_sp *mlxsw_sp = priv;694 695 mlxsw_sp_dpipe_table_host_counters_update(mlxsw_sp, enable, AF_INET);696 return 0;697}698 699static u64700mlxsw_sp_dpipe_table_host_size_get(struct mlxsw_sp *mlxsw_sp, int type)701{702 u64 size = 0;703 int i;704 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;709 710 if (!rif)711 continue;712 mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {713 int neigh_type = mlxsw_sp_neigh_entry_type(neigh_entry);714 715 if (neigh_type != type)716 continue;717 718 if (neigh_type == AF_INET6 &&719 mlxsw_sp_neigh_ipv6_ignore(neigh_entry))720 continue;721 722 size++;723 }724 }725 mutex_unlock(&mlxsw_sp->router->lock);726 727 return size;728}729 730static u64 mlxsw_sp_dpipe_table_host4_size_get(void *priv)731{732 struct mlxsw_sp *mlxsw_sp = priv;733 734 return mlxsw_sp_dpipe_table_host_size_get(mlxsw_sp, AF_INET);735}736 737static const 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,743};744 745#define MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST4 1746 747static int mlxsw_sp_dpipe_host4_table_init(struct mlxsw_sp *mlxsw_sp)748{749 struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);750 int err;751 752 err = devl_dpipe_table_register(devlink,753 MLXSW_SP_DPIPE_TABLE_NAME_HOST4,754 &mlxsw_sp_host4_ops,755 mlxsw_sp, false);756 if (err)757 return err;758 759 err = devl_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);763 if (err)764 goto err_resource_set;765 766 return 0;767 768err_resource_set:769 devl_dpipe_table_unregister(devlink,770 MLXSW_SP_DPIPE_TABLE_NAME_HOST4);771 return err;772}773 774static void mlxsw_sp_dpipe_host4_table_fini(struct mlxsw_sp *mlxsw_sp)775{776 struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);777 778 devl_dpipe_table_unregister(devlink,779 MLXSW_SP_DPIPE_TABLE_NAME_HOST4);780}781 782static int783mlxsw_sp_dpipe_table_host6_matches_dump(void *priv, struct sk_buff *skb)784{785 return mlxsw_sp_dpipe_table_host_matches_dump(skb, AF_INET6);786}787 788static int789mlxsw_sp_dpipe_table_host6_entries_dump(void *priv, bool counters_enabled,790 struct devlink_dpipe_dump_ctx *dump_ctx)791{792 struct mlxsw_sp *mlxsw_sp = priv;793 794 return mlxsw_sp_dpipe_table_host_entries_dump(mlxsw_sp,795 counters_enabled,796 dump_ctx, AF_INET6);797}798 799static int mlxsw_sp_dpipe_table_host6_counters_update(void *priv, bool enable)800{801 struct mlxsw_sp *mlxsw_sp = priv;802 803 mlxsw_sp_dpipe_table_host_counters_update(mlxsw_sp, enable, AF_INET6);804 return 0;805}806 807static u64 mlxsw_sp_dpipe_table_host6_size_get(void *priv)808{809 struct mlxsw_sp *mlxsw_sp = priv;810 811 return mlxsw_sp_dpipe_table_host_size_get(mlxsw_sp, AF_INET6);812}813 814static const 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,820};821 822#define MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_HOST6 2823 824static int mlxsw_sp_dpipe_host6_table_init(struct mlxsw_sp *mlxsw_sp)825{826 struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);827 int err;828 829 err = devl_dpipe_table_register(devlink,830 MLXSW_SP_DPIPE_TABLE_NAME_HOST6,831 &mlxsw_sp_host6_ops,832 mlxsw_sp, false);833 if (err)834 return err;835 836 err = devl_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);840 if (err)841 goto err_resource_set;842 843 return 0;844 845err_resource_set:846 devl_dpipe_table_unregister(devlink,847 MLXSW_SP_DPIPE_TABLE_NAME_HOST6);848 return err;849}850 851static void mlxsw_sp_dpipe_host6_table_fini(struct mlxsw_sp *mlxsw_sp)852{853 struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);854 855 devl_dpipe_table_unregister(devlink,856 MLXSW_SP_DPIPE_TABLE_NAME_HOST6);857}858 859static int mlxsw_sp_dpipe_table_adj_matches_dump(void *priv,860 struct sk_buff *skb)861{862 struct devlink_dpipe_match match = {0};863 int err;864 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;868 869 err = devlink_dpipe_match_put(skb, &match);870 if (err)871 return err;872 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;876 877 err = devlink_dpipe_match_put(skb, &match);878 if (err)879 return err;880 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;884 885 return devlink_dpipe_match_put(skb, &match);886}887 888static int mlxsw_sp_dpipe_table_adj_actions_dump(void *priv,889 struct sk_buff *skb)890{891 struct devlink_dpipe_action action = {0};892 int err;893 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;897 898 err = devlink_dpipe_action_put(skb, &action);899 if (err)900 return err;901 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;905 906 return devlink_dpipe_action_put(skb, &action);907}908 909static u64 mlxsw_sp_dpipe_table_adj_size(struct mlxsw_sp *mlxsw_sp)910{911 struct mlxsw_sp_nexthop *nh;912 u64 size = 0;913 914 mlxsw_sp_nexthop_for_each(nh, mlxsw_sp->router)915 if (mlxsw_sp_nexthop_is_forward(nh) &&916 !mlxsw_sp_nexthop_group_has_ipip(nh))917 size++;918 return size;919}920 921enum 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,926};927 928enum 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,932};933 934static void935mlxsw_sp_dpipe_table_adj_match_action_prepare(struct devlink_dpipe_match *matches,936 struct devlink_dpipe_action *actions)937{938 struct devlink_dpipe_action *action;939 struct devlink_dpipe_match *match;940 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;945 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;950 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;955 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;960 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;965}966 967static int968mlxsw_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;977 978 entry->match_values = match_values;979 entry->match_values_count = MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_COUNT;980 981 entry->action_values = action_values;982 entry->action_values_count = MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_COUNT;983 984 match = &matches[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX];985 match_value = &match_values[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX];986 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)991 return -ENOMEM;992 993 match = &matches[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE];994 match_value = &match_values[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE];995 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)1000 return -ENOMEM;1001 1002 match = &matches[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX];1003 match_value = &match_values[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX];1004 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)1009 return -ENOMEM;1010 1011 action = &actions[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC];1012 action_value = &action_values[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC];1013 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)1018 return -ENOMEM;1019 1020 action = &actions[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT];1021 action_value = &action_values[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_ERIF_PORT];1022 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)1027 return -ENOMEM;1028 1029 return 0;1030}1031 1032static void1033__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)1037{1038 struct devlink_dpipe_value *value;1039 u32 *p_rif_value;1040 u32 *p_index;1041 1042 value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_INDEX];1043 p_index = value->value;1044 *p_index = adj_index;1045 1046 value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_SIZE];1047 p_index = value->value;1048 *p_index = adj_size;1049 1050 value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_ADJ_MATCH_HASH_INDEX];1051 p_index = value->value;1052 *p_index = adj_hash_index;1053 1054 value = &entry->action_values[MLXSW_SP_DPIPE_TABLE_ADJ_ACTION_DST_MAC];1055 ether_addr_copy(value->value, ha);1056 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;1062}1063 1064static 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)1067{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;1071 u32 adj_index = 0;1072 u32 adj_size = 0;1073 int err;1074 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);1079 if (!err)1080 entry->counter_valid = true;1081}1082 1083static int1084mlxsw_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)1088{1089 struct mlxsw_sp_nexthop *nh;1090 int entry_index = 0;1091 int nh_count_max;1092 int nh_count = 0;1093 int nh_skip;1094 int j;1095 int err;1096 1097 mutex_lock(&mlxsw_sp->router->lock);1098 nh_count_max = mlxsw_sp_dpipe_table_adj_size(mlxsw_sp);1099start_again:1100 err = devlink_dpipe_entry_ctx_prepare(dump_ctx);1101 if (err)1102 goto err_ctx_prepare;1103 j = 0;1104 nh_skip = nh_count;1105 nh_count = 0;1106 mlxsw_sp_nexthop_for_each(nh, mlxsw_sp->router) {1107 if (!mlxsw_sp_nexthop_is_forward(nh) ||1108 mlxsw_sp_nexthop_group_has_ipip(nh))1109 continue;1110 1111 if (nh_count < nh_skip)1112 goto skip;1113 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);1117 if (err) {1118 if (err == -EMSGSIZE) {1119 if (!j)1120 goto err_entry_append;1121 break;1122 }1123 goto err_entry_append;1124 }1125 entry_index++;1126 j++;1127skip:1128 nh_count++;1129 }1130 1131 devlink_dpipe_entry_ctx_close(dump_ctx);1132 if (nh_count != nh_count_max)1133 goto start_again;1134 mutex_unlock(&mlxsw_sp->router->lock);1135 1136 return 0;1137 1138err_ctx_prepare:1139err_entry_append:1140 mutex_unlock(&mlxsw_sp->router->lock);1141 return err;1142}1143 1144static int1145mlxsw_sp_dpipe_table_adj_entries_dump(void *priv, bool counters_enabled,1146 struct devlink_dpipe_dump_ctx *dump_ctx)1147{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;1154 int err;1155 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]));1164 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);1169 if (err)1170 goto out;1171 1172 err = mlxsw_sp_dpipe_table_adj_entries_get(mlxsw_sp, &entry,1173 counters_enabled, dump_ctx);1174out:1175 devlink_dpipe_entry_clear(&entry);1176 return err;1177}1178 1179static int mlxsw_sp_dpipe_table_adj_counters_update(void *priv, bool enable)1180{1181 char ratr_pl[MLXSW_REG_RATR_LEN];1182 struct mlxsw_sp *mlxsw_sp = priv;1183 struct mlxsw_sp_nexthop *nh;1184 unsigned int n_done = 0;1185 u32 adj_hash_index = 0;1186 u32 adj_index = 0;1187 u32 adj_size = 0;1188 int err;1189 1190 mlxsw_sp_nexthop_for_each(nh, mlxsw_sp->router) {1191 if (!mlxsw_sp_nexthop_is_forward(nh) ||1192 mlxsw_sp_nexthop_group_has_ipip(nh))1193 continue;1194 1195 mlxsw_sp_nexthop_indexes(nh, &adj_index, &adj_size,1196 &adj_hash_index);1197 if (enable) {1198 err = mlxsw_sp_nexthop_counter_enable(mlxsw_sp, nh);1199 if (err)1200 goto err_counter_enable;1201 } else {1202 mlxsw_sp_nexthop_counter_disable(mlxsw_sp, nh);1203 }1204 mlxsw_sp_nexthop_eth_update(mlxsw_sp,1205 adj_index + adj_hash_index, nh,1206 true, ratr_pl);1207 n_done++;1208 }1209 return 0;1210 1211err_counter_enable:1212 mlxsw_sp_nexthop_for_each(nh, mlxsw_sp->router) {1213 if (!n_done--)1214 break;1215 mlxsw_sp_nexthop_counter_disable(mlxsw_sp, nh);1216 }1217 return err;1218}1219 1220static u641221mlxsw_sp_dpipe_table_adj_size_get(void *priv)1222{1223 struct mlxsw_sp *mlxsw_sp = priv;1224 u64 size;1225 1226 mutex_lock(&mlxsw_sp->router->lock);1227 size = mlxsw_sp_dpipe_table_adj_size(mlxsw_sp);1228 mutex_unlock(&mlxsw_sp->router->lock);1229 1230 return size;1231}1232 1233static const struct devlink_dpipe_table_ops mlxsw_sp_dpipe_table_adj_ops = {1234 .matches_dump = mlxsw_sp_dpipe_table_adj_matches_dump,1235 .actions_dump = mlxsw_sp_dpipe_table_adj_actions_dump,1236 .entries_dump = mlxsw_sp_dpipe_table_adj_entries_dump,1237 .counters_set_update = mlxsw_sp_dpipe_table_adj_counters_update,1238 .size_get = mlxsw_sp_dpipe_table_adj_size_get,1239};1240 1241#define MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_ADJ 11242 1243static int mlxsw_sp_dpipe_adj_table_init(struct mlxsw_sp *mlxsw_sp)1244{1245 struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);1246 int err;1247 1248 err = devl_dpipe_table_register(devlink,1249 MLXSW_SP_DPIPE_TABLE_NAME_ADJ,1250 &mlxsw_sp_dpipe_table_adj_ops,1251 mlxsw_sp, false);1252 if (err)1253 return err;1254 1255 err = devl_dpipe_table_resource_set(devlink,1256 MLXSW_SP_DPIPE_TABLE_NAME_ADJ,1257 MLXSW_SP_RESOURCE_KVD_LINEAR,1258 MLXSW_SP_DPIPE_TABLE_RESOURCE_UNIT_ADJ);1259 if (err)1260 goto err_resource_set;1261 1262 return 0;1263 1264err_resource_set:1265 devl_dpipe_table_unregister(devlink,1266 MLXSW_SP_DPIPE_TABLE_NAME_ADJ);1267 return err;1268}1269 1270static void mlxsw_sp_dpipe_adj_table_fini(struct mlxsw_sp *mlxsw_sp)1271{1272 struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);1273 1274 devl_dpipe_table_unregister(devlink,1275 MLXSW_SP_DPIPE_TABLE_NAME_ADJ);1276}1277 1278int mlxsw_sp_dpipe_init(struct mlxsw_sp *mlxsw_sp)1279{1280 struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);1281 int err;1282 1283 devl_dpipe_headers_register(devlink, &mlxsw_sp_dpipe_headers);1284 1285 err = mlxsw_sp_dpipe_erif_table_init(mlxsw_sp);1286 if (err)1287 goto err_erif_table_init;1288 1289 err = mlxsw_sp_dpipe_host4_table_init(mlxsw_sp);1290 if (err)1291 goto err_host4_table_init;1292 1293 err = mlxsw_sp_dpipe_host6_table_init(mlxsw_sp);1294 if (err)1295 goto err_host6_table_init;1296 1297 err = mlxsw_sp_dpipe_adj_table_init(mlxsw_sp);1298 if (err)1299 goto err_adj_table_init;1300 1301 return 0;1302err_adj_table_init:1303 mlxsw_sp_dpipe_host6_table_fini(mlxsw_sp);1304err_host6_table_init:1305 mlxsw_sp_dpipe_host4_table_fini(mlxsw_sp);1306err_host4_table_init:1307 mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp);1308err_erif_table_init:1309 devl_dpipe_headers_unregister(priv_to_devlink(mlxsw_sp->core));1310 return err;1311}1312 1313void mlxsw_sp_dpipe_fini(struct mlxsw_sp *mlxsw_sp)1314{1315 struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);1316 1317 mlxsw_sp_dpipe_adj_table_fini(mlxsw_sp);1318 mlxsw_sp_dpipe_host6_table_fini(mlxsw_sp);1319 mlxsw_sp_dpipe_host4_table_fini(mlxsw_sp);1320 mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp);1321 devl_dpipe_headers_unregister(devlink);1322}1323