FILE
port_sel.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2/* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. */ 3 4#include <linux/netdevice.h> 5#include "lag.h" 6 7enum { 8 MLX5_LAG_FT_LEVEL_TTC, 9 MLX5_LAG_FT_LEVEL_INNER_TTC, 10 MLX5_LAG_FT_LEVEL_DEFINER, 11}; 12 13static struct mlx5_flow_group * 14mlx5_create_hash_flow_group(struct mlx5_flow_table *ft, 15 struct mlx5_flow_definer *definer, 16 u8 rules) 17{ 18 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 19 struct mlx5_flow_group *fg; 20 u32 *in; 21 22 in = kvzalloc(inlen, GFP_KERNEL); 23 if (!in) 24 return ERR_PTR(-ENOMEM); 25 26 MLX5_SET(create_flow_group_in, in, match_definer_id, 27 mlx5_get_match_definer_id(definer)); 28 MLX5_SET(create_flow_group_in, in, start_flow_index, 0); 29 MLX5_SET(create_flow_group_in, in, end_flow_index, rules - 1); 30 MLX5_SET(create_flow_group_in, in, group_type, 31 MLX5_CREATE_FLOW_GROUP_IN_GROUP_TYPE_HASH_SPLIT); 32 33 fg = mlx5_create_flow_group(ft, in); 34 kvfree(in); 35 return fg; 36} 37 38static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev, 39 struct mlx5_lag_definer *lag_definer, 40 u8 *ports) 41{ 42 int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 43 struct mlx5_flow_table_attr ft_attr = {}; 44 struct mlx5_flow_destination dest = {}; 45 MLX5_DECLARE_FLOW_ACT(flow_act); 46 struct mlx5_flow_namespace *ns; 47 struct mlx5_core_dev *dev; 48 int err, i, j, k, idx; 49 50 if (first_idx < 0) 51 return -EINVAL; 52 53 dev = ldev->pf[first_idx].dev; 54 ft_attr.max_fte = ldev->ports * ldev->buckets; 55 ft_attr.level = MLX5_LAG_FT_LEVEL_DEFINER; 56 57 ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_PORT_SEL); 58 if (!ns) { 59 mlx5_core_warn(dev, "Failed to get port selection namespace\n"); 60 return -EOPNOTSUPP; 61 } 62 63 lag_definer->ft = mlx5_create_flow_table(ns, &ft_attr); 64 if (IS_ERR(lag_definer->ft)) { 65 mlx5_core_warn(dev, "Failed to create port selection table\n"); 66 return PTR_ERR(lag_definer->ft); 67 } 68 69 lag_definer->fg = mlx5_create_hash_flow_group(lag_definer->ft, 70 lag_definer->definer, 71 ft_attr.max_fte); 72 if (IS_ERR(lag_definer->fg)) { 73 err = PTR_ERR(lag_definer->fg); 74 goto destroy_ft; 75 } 76 77 dest.type = MLX5_FLOW_DESTINATION_TYPE_UPLINK; 78 dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID; 79 flow_act.flags |= FLOW_ACT_NO_APPEND; 80 mlx5_ldev_for_each(i, 0, ldev) { 81 for (j = 0; j < ldev->buckets; j++) { 82 u8 affinity; 83 84 idx = i * ldev->buckets + j; 85 affinity = ports[idx]; 86 87 dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[affinity - 1].dev, 88 vhca_id); 89 lag_definer->rules[idx] = mlx5_add_flow_rules(lag_definer->ft, 90 NULL, &flow_act, 91 &dest, 1); 92 if (IS_ERR(lag_definer->rules[idx])) { 93 err = PTR_ERR(lag_definer->rules[idx]); 94 mlx5_ldev_for_each_reverse(k, i, 0, ldev) { 95 while (j--) { 96 idx = k * ldev->buckets + j; 97 mlx5_del_flow_rules(lag_definer->rules[idx]); 98 } 99 j = ldev->buckets; 100 } 101 goto destroy_fg; 102 } 103 } 104 } 105 106 return 0; 107 108destroy_fg: 109 mlx5_destroy_flow_group(lag_definer->fg); 110destroy_ft: 111 mlx5_destroy_flow_table(lag_definer->ft); 112 return err; 113} 114 115static int mlx5_lag_set_definer_inner(u32 *match_definer_mask, 116 enum mlx5_traffic_types tt) 117{ 118 int format_id; 119 u8 *ipv6; 120 121 switch (tt) { 122 case MLX5_TT_IPV4_UDP: 123 case MLX5_TT_IPV4_TCP: 124 format_id = 23; 125 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 126 inner_l4_sport); 127 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 128 inner_l4_dport); 129 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 130 inner_ip_src_addr); 131 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 132 inner_ip_dest_addr); 133 break; 134 case MLX5_TT_IPV4: 135 format_id = 23; 136 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 137 inner_l3_type); 138 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 139 inner_dmac_47_16); 140 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 141 inner_dmac_15_0); 142 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 143 inner_smac_47_16); 144 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 145 inner_smac_15_0); 146 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 147 inner_ip_src_addr); 148 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 149 inner_ip_dest_addr); 150 break; 151 case MLX5_TT_IPV6_TCP: 152 case MLX5_TT_IPV6_UDP: 153 format_id = 31; 154 MLX5_SET_TO_ONES(match_definer_format_31, match_definer_mask, 155 inner_l4_sport); 156 MLX5_SET_TO_ONES(match_definer_format_31, match_definer_mask, 157 inner_l4_dport); 158 ipv6 = MLX5_ADDR_OF(match_definer_format_31, match_definer_mask, 159 inner_ip_dest_addr); 160 memset(ipv6, 0xff, 16); 161 ipv6 = MLX5_ADDR_OF(match_definer_format_31, match_definer_mask, 162 inner_ip_src_addr); 163 memset(ipv6, 0xff, 16); 164 break; 165 case MLX5_TT_IPV6: 166 format_id = 32; 167 ipv6 = MLX5_ADDR_OF(match_definer_format_32, match_definer_mask, 168 inner_ip_dest_addr); 169 memset(ipv6, 0xff, 16); 170 ipv6 = MLX5_ADDR_OF(match_definer_format_32, match_definer_mask, 171 inner_ip_src_addr); 172 memset(ipv6, 0xff, 16); 173 MLX5_SET_TO_ONES(match_definer_format_32, match_definer_mask, 174 inner_dmac_47_16); 175 MLX5_SET_TO_ONES(match_definer_format_32, match_definer_mask, 176 inner_dmac_15_0); 177 MLX5_SET_TO_ONES(match_definer_format_32, match_definer_mask, 178 inner_smac_47_16); 179 MLX5_SET_TO_ONES(match_definer_format_32, match_definer_mask, 180 inner_smac_15_0); 181 break; 182 default: 183 format_id = 23; 184 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 185 inner_l3_type); 186 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 187 inner_dmac_47_16); 188 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 189 inner_dmac_15_0); 190 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 191 inner_smac_47_16); 192 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask, 193 inner_smac_15_0); 194 break; 195 } 196 197 return format_id; 198} 199 200static int mlx5_lag_set_definer(u32 *match_definer_mask, 201 enum mlx5_traffic_types tt, bool tunnel, 202 enum netdev_lag_hash hash) 203{ 204 int format_id; 205 u8 *ipv6; 206 207 if (tunnel) 208 return mlx5_lag_set_definer_inner(match_definer_mask, tt); 209 210 switch (tt) { 211 case MLX5_TT_IPV4_UDP: 212 case MLX5_TT_IPV4_TCP: 213 format_id = 22; 214 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask, 215 outer_l4_sport); 216 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask, 217 outer_l4_dport); 218 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask, 219 outer_ip_src_addr); 220 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask, 221 outer_ip_dest_addr); 222 break; 223 case MLX5_TT_IPV4: 224 format_id = 22; 225 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask, 226 outer_l3_type); 227 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask, 228 outer_dmac_47_16); 229 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask, 230 outer_dmac_15_0); 231 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask, 232 outer_smac_47_16); 233 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask, 234 outer_smac_15_0); 235 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask, 236 outer_ip_src_addr); 237 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask, 238 outer_ip_dest_addr); 239 break; 240 case MLX5_TT_IPV6_TCP: 241 case MLX5_TT_IPV6_UDP: 242 format_id = 29; 243 MLX5_SET_TO_ONES(match_definer_format_29, match_definer_mask, 244 outer_l4_sport); 245 MLX5_SET_TO_ONES(match_definer_format_29, match_definer_mask, 246 outer_l4_dport); 247 ipv6 = MLX5_ADDR_OF(match_definer_format_29, match_definer_mask, 248 outer_ip_dest_addr); 249 memset(ipv6, 0xff, 16); 250 ipv6 = MLX5_ADDR_OF(match_definer_format_29, match_definer_mask, 251 outer_ip_src_addr); 252 memset(ipv6, 0xff, 16); 253 break; 254 case MLX5_TT_IPV6: 255 format_id = 30; 256 ipv6 = MLX5_ADDR_OF(match_definer_format_30, match_definer_mask, 257 outer_ip_dest_addr); 258 memset(ipv6, 0xff, 16); 259 ipv6 = MLX5_ADDR_OF(match_definer_format_30, match_definer_mask, 260 outer_ip_src_addr); 261 memset(ipv6, 0xff, 16); 262 MLX5_SET_TO_ONES(match_definer_format_30, match_definer_mask, 263 outer_dmac_47_16); 264 MLX5_SET_TO_ONES(match_definer_format_30, match_definer_mask, 265 outer_dmac_15_0); 266 MLX5_SET_TO_ONES(match_definer_format_30, match_definer_mask, 267 outer_smac_47_16); 268 MLX5_SET_TO_ONES(match_definer_format_30, match_definer_mask, 269 outer_smac_15_0); 270 break; 271 default: 272 format_id = 0; 273 MLX5_SET_TO_ONES(match_definer_format_0, match_definer_mask, 274 outer_smac_47_16); 275 MLX5_SET_TO_ONES(match_definer_format_0, match_definer_mask, 276 outer_smac_15_0); 277 278 if (hash == NETDEV_LAG_HASH_VLAN_SRCMAC) { 279 MLX5_SET_TO_ONES(match_definer_format_0, 280 match_definer_mask, 281 outer_first_vlan_vid); 282 break; 283 } 284 285 MLX5_SET_TO_ONES(match_definer_format_0, match_definer_mask, 286 outer_ethertype); 287 MLX5_SET_TO_ONES(match_definer_format_0, match_definer_mask, 288 outer_dmac_47_16); 289 MLX5_SET_TO_ONES(match_definer_format_0, match_definer_mask, 290 outer_dmac_15_0); 291 break; 292 } 293 294 return format_id; 295} 296 297static struct mlx5_lag_definer * 298mlx5_lag_create_definer(struct mlx5_lag *ldev, enum netdev_lag_hash hash, 299 enum mlx5_traffic_types tt, bool tunnel, u8 *ports) 300{ 301 int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 302 struct mlx5_lag_definer *lag_definer; 303 struct mlx5_core_dev *dev; 304 u32 *match_definer_mask; 305 int format_id, err; 306 307 if (first_idx < 0) 308 return ERR_PTR(-EINVAL); 309 310 dev = ldev->pf[first_idx].dev; 311 lag_definer = kzalloc(sizeof(*lag_definer), GFP_KERNEL); 312 if (!lag_definer) 313 return ERR_PTR(-ENOMEM); 314 315 match_definer_mask = kvzalloc(MLX5_FLD_SZ_BYTES(match_definer, 316 match_mask), 317 GFP_KERNEL); 318 if (!match_definer_mask) { 319 err = -ENOMEM; 320 goto free_lag_definer; 321 } 322 323 format_id = mlx5_lag_set_definer(match_definer_mask, tt, tunnel, hash); 324 lag_definer->definer = 325 mlx5_create_match_definer(dev, MLX5_FLOW_NAMESPACE_PORT_SEL, 326 format_id, match_definer_mask); 327 if (IS_ERR(lag_definer->definer)) { 328 err = PTR_ERR(lag_definer->definer); 329 goto free_mask; 330 } 331 332 err = mlx5_lag_create_port_sel_table(ldev, lag_definer, ports); 333 if (err) 334 goto destroy_match_definer; 335 336 kvfree(match_definer_mask); 337 338 return lag_definer; 339 340destroy_match_definer: 341 mlx5_destroy_match_definer(dev, lag_definer->definer); 342free_mask: 343 kvfree(match_definer_mask); 344free_lag_definer: 345 kfree(lag_definer); 346 return ERR_PTR(err); 347} 348 349static void mlx5_lag_destroy_definer(struct mlx5_lag *ldev, 350 struct mlx5_lag_definer *lag_definer) 351{ 352 int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 353 struct mlx5_core_dev *dev; 354 int idx, i, j; 355 356 if (first_idx < 0) 357 return; 358 359 dev = ldev->pf[first_idx].dev; 360 mlx5_ldev_for_each(i, first_idx, ldev) { 361 for (j = 0; j < ldev->buckets; j++) { 362 idx = i * ldev->buckets + j; 363 mlx5_del_flow_rules(lag_definer->rules[idx]); 364 } 365 } 366 mlx5_destroy_flow_group(lag_definer->fg); 367 mlx5_destroy_flow_table(lag_definer->ft); 368 mlx5_destroy_match_definer(dev, lag_definer->definer); 369 kfree(lag_definer); 370} 371 372static void mlx5_lag_destroy_definers(struct mlx5_lag *ldev) 373{ 374 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel; 375 int tt; 376 377 for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) { 378 if (port_sel->outer.definers[tt]) 379 mlx5_lag_destroy_definer(ldev, 380 port_sel->outer.definers[tt]); 381 if (port_sel->inner.definers[tt]) 382 mlx5_lag_destroy_definer(ldev, 383 port_sel->inner.definers[tt]); 384 } 385} 386 387static int mlx5_lag_create_definers(struct mlx5_lag *ldev, 388 enum netdev_lag_hash hash_type, 389 u8 *ports) 390{ 391 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel; 392 struct mlx5_lag_definer *lag_definer; 393 int tt, err; 394 395 for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) { 396 lag_definer = mlx5_lag_create_definer(ldev, hash_type, tt, 397 false, ports); 398 if (IS_ERR(lag_definer)) { 399 err = PTR_ERR(lag_definer); 400 goto destroy_definers; 401 } 402 port_sel->outer.definers[tt] = lag_definer; 403 404 if (!port_sel->tunnel) 405 continue; 406 407 lag_definer = 408 mlx5_lag_create_definer(ldev, hash_type, tt, 409 true, ports); 410 if (IS_ERR(lag_definer)) { 411 err = PTR_ERR(lag_definer); 412 goto destroy_definers; 413 } 414 port_sel->inner.definers[tt] = lag_definer; 415 } 416 417 return 0; 418 419destroy_definers: 420 mlx5_lag_destroy_definers(ldev); 421 return err; 422} 423 424static void set_tt_map(struct mlx5_lag_port_sel *port_sel, 425 enum netdev_lag_hash hash) 426{ 427 port_sel->tunnel = false; 428 429 switch (hash) { 430 case NETDEV_LAG_HASH_E34: 431 port_sel->tunnel = true; 432 fallthrough; 433 case NETDEV_LAG_HASH_L34: 434 set_bit(MLX5_TT_IPV4_TCP, port_sel->tt_map); 435 set_bit(MLX5_TT_IPV4_UDP, port_sel->tt_map); 436 set_bit(MLX5_TT_IPV6_TCP, port_sel->tt_map); 437 set_bit(MLX5_TT_IPV6_UDP, port_sel->tt_map); 438 set_bit(MLX5_TT_IPV4, port_sel->tt_map); 439 set_bit(MLX5_TT_IPV6, port_sel->tt_map); 440 set_bit(MLX5_TT_ANY, port_sel->tt_map); 441 break; 442 case NETDEV_LAG_HASH_E23: 443 port_sel->tunnel = true; 444 fallthrough; 445 case NETDEV_LAG_HASH_L23: 446 set_bit(MLX5_TT_IPV4, port_sel->tt_map); 447 set_bit(MLX5_TT_IPV6, port_sel->tt_map); 448 set_bit(MLX5_TT_ANY, port_sel->tt_map); 449 break; 450 default: 451 set_bit(MLX5_TT_ANY, port_sel->tt_map); 452 break; 453 } 454} 455 456#define SET_IGNORE_DESTS_BITS(tt_map, dests) \ 457 do { \ 458 int idx; \ 459 \ 460 for_each_clear_bit(idx, tt_map, MLX5_NUM_TT) \ 461 set_bit(idx, dests); \ 462 } while (0) 463 464static void mlx5_lag_set_inner_ttc_params(struct mlx5_lag *ldev, 465 struct ttc_params *ttc_params) 466{ 467 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel; 468 struct mlx5_flow_table_attr *ft_attr; 469 int tt; 470 471 ttc_params->ns_type = MLX5_FLOW_NAMESPACE_PORT_SEL; 472 ft_attr = &ttc_params->ft_attr; 473 ft_attr->level = MLX5_LAG_FT_LEVEL_INNER_TTC; 474 475 for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) { 476 ttc_params->dests[tt].type = 477 MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 478 ttc_params->dests[tt].ft = port_sel->inner.definers[tt]->ft; 479 } 480 SET_IGNORE_DESTS_BITS(port_sel->tt_map, ttc_params->ignore_dests); 481} 482 483static void mlx5_lag_set_outer_ttc_params(struct mlx5_lag *ldev, 484 struct ttc_params *ttc_params) 485{ 486 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel; 487 struct mlx5_flow_table_attr *ft_attr; 488 int tt; 489 490 ttc_params->ns_type = MLX5_FLOW_NAMESPACE_PORT_SEL; 491 ft_attr = &ttc_params->ft_attr; 492 ft_attr->level = MLX5_LAG_FT_LEVEL_TTC; 493 494 for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) { 495 ttc_params->dests[tt].type = 496 MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 497 ttc_params->dests[tt].ft = port_sel->outer.definers[tt]->ft; 498 } 499 SET_IGNORE_DESTS_BITS(port_sel->tt_map, ttc_params->ignore_dests); 500 501 ttc_params->inner_ttc = port_sel->tunnel; 502 if (!port_sel->tunnel) 503 return; 504 505 for (tt = 0; tt < MLX5_NUM_TUNNEL_TT; tt++) { 506 ttc_params->tunnel_dests[tt].type = 507 MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 508 ttc_params->tunnel_dests[tt].ft = 509 mlx5_get_ttc_flow_table(port_sel->inner.ttc); 510 } 511} 512 513static int mlx5_lag_create_ttc_table(struct mlx5_lag *ldev) 514{ 515 int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 516 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel; 517 struct ttc_params ttc_params = {}; 518 struct mlx5_core_dev *dev; 519 520 if (first_idx < 0) 521 return -EINVAL; 522 523 dev = ldev->pf[first_idx].dev; 524 mlx5_lag_set_outer_ttc_params(ldev, &ttc_params); 525 port_sel->outer.ttc = mlx5_create_ttc_table(dev, &ttc_params); 526 return PTR_ERR_OR_ZERO(port_sel->outer.ttc); 527} 528 529static int mlx5_lag_create_inner_ttc_table(struct mlx5_lag *ldev) 530{ 531 int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 532 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel; 533 struct ttc_params ttc_params = {}; 534 struct mlx5_core_dev *dev; 535 536 if (first_idx < 0) 537 return -EINVAL; 538 539 dev = ldev->pf[first_idx].dev; 540 mlx5_lag_set_inner_ttc_params(ldev, &ttc_params); 541 port_sel->inner.ttc = mlx5_create_inner_ttc_table(dev, &ttc_params); 542 return PTR_ERR_OR_ZERO(port_sel->inner.ttc); 543} 544 545int mlx5_lag_port_sel_create(struct mlx5_lag *ldev, 546 enum netdev_lag_hash hash_type, u8 *ports) 547{ 548 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel; 549 int err; 550 551 set_tt_map(port_sel, hash_type); 552 err = mlx5_lag_create_definers(ldev, hash_type, ports); 553 if (err) 554 goto clear_port_sel; 555 556 if (port_sel->tunnel) { 557 err = mlx5_lag_create_inner_ttc_table(ldev); 558 if (err) 559 goto destroy_definers; 560 } 561 562 err = mlx5_lag_create_ttc_table(ldev); 563 if (err) 564 goto destroy_inner; 565 566 return 0; 567 568destroy_inner: 569 if (port_sel->tunnel) 570 mlx5_destroy_ttc_table(port_sel->inner.ttc); 571destroy_definers: 572 mlx5_lag_destroy_definers(ldev); 573clear_port_sel: 574 memset(port_sel, 0, sizeof(*port_sel)); 575 return err; 576} 577 578static int __mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev, 579 struct mlx5_lag_definer *def, 580 u8 *ports) 581{ 582 struct mlx5_flow_destination dest = {}; 583 int idx; 584 int err; 585 int i; 586 int j; 587 588 dest.type = MLX5_FLOW_DESTINATION_TYPE_UPLINK; 589 dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID; 590 591 mlx5_ldev_for_each(i, 0, ldev) { 592 for (j = 0; j < ldev->buckets; j++) { 593 idx = i * ldev->buckets + j; 594 if (ldev->v2p_map[idx] == ports[idx]) 595 continue; 596 597 dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[ports[idx] - 1].dev, 598 vhca_id); 599 err = mlx5_modify_rule_destination(def->rules[idx], &dest, NULL); 600 if (err) 601 return err; 602 } 603 } 604 605 return 0; 606} 607 608static int 609mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev, 610 struct mlx5_lag_definer **definers, 611 u8 *ports) 612{ 613 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel; 614 int err; 615 int tt; 616 617 for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) { 618 err = __mlx5_lag_modify_definers_destinations(ldev, definers[tt], ports); 619 if (err) 620 return err; 621 } 622 623 return 0; 624} 625 626int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 *ports) 627{ 628 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel; 629 int err; 630 631 err = mlx5_lag_modify_definers_destinations(ldev, 632 port_sel->outer.definers, 633 ports); 634 if (err) 635 return err; 636 637 if (!port_sel->tunnel) 638 return 0; 639 640 return mlx5_lag_modify_definers_destinations(ldev, 641 port_sel->inner.definers, 642 ports); 643} 644 645void mlx5_lag_port_sel_destroy(struct mlx5_lag *ldev) 646{ 647 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel; 648 649 mlx5_destroy_ttc_table(port_sel->outer.ttc); 650 if (port_sel->tunnel) 651 mlx5_destroy_ttc_table(port_sel->inner.ttc); 652 mlx5_lag_destroy_definers(ldev); 653 memset(port_sel, 0, sizeof(*port_sel)); 654}
~/
Read-only file preview.