FILE
en_tc.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
1/* 2 * Copyright (c) 2016, Mellanox Technologies. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33#include <net/flow_dissector.h> 34#include <net/flow_offload.h> 35#include <net/sch_generic.h> 36#include <net/pkt_cls.h> 37#include <linux/mlx5/fs.h> 38#include <linux/mlx5/device.h> 39#include <linux/rhashtable.h> 40#include <linux/refcount.h> 41#include <linux/completion.h> 42#include <net/arp.h> 43#include <net/ipv6_stubs.h> 44#include <net/bareudp.h> 45#include <net/bonding.h> 46#include <net/dst_metadata.h> 47#include "devlink.h" 48#include "en.h" 49#include "en/tc/post_act.h" 50#include "en/tc/act_stats.h" 51#include "en_rep.h" 52#include "en/rep/tc.h" 53#include "en/rep/neigh.h" 54#include "en_tc.h" 55#include "eswitch.h" 56#include "fs_core.h" 57#include "en/port.h" 58#include "en/tc_tun.h" 59#include "en/mapping.h" 60#include "en/tc_ct.h" 61#include "en/mod_hdr.h" 62#include "en/tc_tun_encap.h" 63#include "en/tc/sample.h" 64#include "en/tc/act/act.h" 65#include "en/tc/post_meter.h" 66#include "lib/devcom.h" 67#include "lib/geneve.h" 68#include "lib/fs_chains.h" 69#include "lib/mlx5.h" 70#include "diag/en_tc_tracepoint.h" 71#include <asm/div64.h> 72#include "lag/lag.h" 73#include "lag/mp.h" 74 75#define MLX5E_TC_TABLE_NUM_GROUPS 4 76#define MLX5E_TC_TABLE_MAX_GROUP_SIZE BIT(18) 77 78struct mlx5e_tc_table { 79 /* Protects the dynamic assignment of the t parameter 80 * which is the nic tc root table. 81 */ 82 struct mutex t_lock; 83 struct mlx5e_priv *priv; 84 struct mlx5_flow_table *t; 85 struct mlx5_flow_table *miss_t; 86 struct mlx5_fs_chains *chains; 87 struct mlx5e_post_act *post_act; 88 89 struct rhashtable ht; 90 91 struct mod_hdr_tbl mod_hdr; 92 struct mutex hairpin_tbl_lock; /* protects hairpin_tbl */ 93 DECLARE_HASHTABLE(hairpin_tbl, 8); 94 95 struct notifier_block netdevice_nb; 96 struct netdev_net_notifier netdevice_nn; 97 98 struct mlx5_tc_ct_priv *ct; 99 struct mapping_ctx *mapping; 100 struct dentry *dfs_root; 101 102 /* tc action stats */ 103 struct mlx5e_tc_act_stats_handle *action_stats_handle; 104}; 105 106struct mlx5e_tc_attr_to_reg_mapping mlx5e_tc_attr_to_reg_mappings[] = { 107 [MAPPED_OBJ_TO_REG] = { 108 .mfield = MLX5_ACTION_IN_FIELD_METADATA_REG_C_0, 109 .moffset = 0, 110 .mlen = 16, 111 }, 112 [VPORT_TO_REG] = { 113 .mfield = MLX5_ACTION_IN_FIELD_METADATA_REG_C_0, 114 .moffset = 16, 115 .mlen = 16, 116 }, 117 [TUNNEL_TO_REG] = { 118 .mfield = MLX5_ACTION_IN_FIELD_METADATA_REG_C_1, 119 .moffset = 8, 120 .mlen = ESW_TUN_OPTS_BITS + ESW_TUN_ID_BITS, 121 .soffset = MLX5_BYTE_OFF(fte_match_param, 122 misc_parameters_2.metadata_reg_c_1), 123 }, 124 [ZONE_TO_REG] = zone_to_reg_ct, 125 [ZONE_RESTORE_TO_REG] = zone_restore_to_reg_ct, 126 [CTSTATE_TO_REG] = ctstate_to_reg_ct, 127 [MARK_TO_REG] = mark_to_reg_ct, 128 [LABELS_TO_REG] = labels_to_reg_ct, 129 [FTEID_TO_REG] = fteid_to_reg_ct, 130 /* For NIC rules we store the restore metadata directly 131 * into reg_b that is passed to SW since we don't 132 * jump between steering domains. 133 */ 134 [NIC_MAPPED_OBJ_TO_REG] = { 135 .mfield = MLX5_ACTION_IN_FIELD_METADATA_REG_B, 136 .moffset = 0, 137 .mlen = 16, 138 }, 139 [NIC_ZONE_RESTORE_TO_REG] = nic_zone_restore_to_reg_ct, 140 [PACKET_COLOR_TO_REG] = packet_color_to_reg, 141}; 142 143struct mlx5e_tc_jump_state { 144 u32 jump_count; 145 bool jump_target; 146 struct mlx5_flow_attr *jumping_attr; 147 148 enum flow_action_id last_id; 149 u32 last_index; 150}; 151 152struct mlx5e_tc_table *mlx5e_tc_table_alloc(void) 153{ 154 struct mlx5e_tc_table *tc; 155 156 tc = kvzalloc(sizeof(*tc), GFP_KERNEL); 157 return tc ? tc : ERR_PTR(-ENOMEM); 158} 159 160void mlx5e_tc_table_free(struct mlx5e_tc_table *tc) 161{ 162 kvfree(tc); 163} 164 165struct mlx5_fs_chains *mlx5e_nic_chains(struct mlx5e_tc_table *tc) 166{ 167 return tc->chains; 168} 169 170/* To avoid false lock dependency warning set the tc_ht lock 171 * class different than the lock class of the ht being used when deleting 172 * last flow from a group and then deleting a group, we get into del_sw_flow_group() 173 * which call rhashtable_destroy on fg->ftes_hash which will take ht->mutex but 174 * it's different than the ht->mutex here. 175 */ 176static struct lock_class_key tc_ht_lock_key; 177static struct lock_class_key tc_ht_wq_key; 178 179static void mlx5e_put_flow_tunnel_id(struct mlx5e_tc_flow *flow); 180static void free_flow_post_acts(struct mlx5e_tc_flow *flow); 181static void mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, 182 struct mlx5_flow_attr *attr); 183 184void 185mlx5e_tc_match_to_reg_match(struct mlx5_flow_spec *spec, 186 enum mlx5e_tc_attr_to_reg type, 187 u32 val, 188 u32 mask) 189{ 190 void *headers_c = spec->match_criteria, *headers_v = spec->match_value, *fmask, *fval; 191 int soffset = mlx5e_tc_attr_to_reg_mappings[type].soffset; 192 int moffset = mlx5e_tc_attr_to_reg_mappings[type].moffset; 193 int match_len = mlx5e_tc_attr_to_reg_mappings[type].mlen; 194 u32 max_mask = GENMASK(match_len - 1, 0); 195 __be32 curr_mask_be, curr_val_be; 196 u32 curr_mask, curr_val; 197 198 fmask = headers_c + soffset; 199 fval = headers_v + soffset; 200 201 memcpy(&curr_mask_be, fmask, 4); 202 memcpy(&curr_val_be, fval, 4); 203 204 curr_mask = be32_to_cpu(curr_mask_be); 205 curr_val = be32_to_cpu(curr_val_be); 206 207 //move to correct offset 208 WARN_ON(mask > max_mask); 209 mask <<= moffset; 210 val <<= moffset; 211 max_mask <<= moffset; 212 213 //zero val and mask 214 curr_mask &= ~max_mask; 215 curr_val &= ~max_mask; 216 217 //add current to mask 218 curr_mask |= mask; 219 curr_val |= val; 220 221 //back to be32 and write 222 curr_mask_be = cpu_to_be32(curr_mask); 223 curr_val_be = cpu_to_be32(curr_val); 224 225 memcpy(fmask, &curr_mask_be, 4); 226 memcpy(fval, &curr_val_be, 4); 227 228 spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; 229} 230 231void 232mlx5e_tc_match_to_reg_get_match(struct mlx5_flow_spec *spec, 233 enum mlx5e_tc_attr_to_reg type, 234 u32 *val, 235 u32 *mask) 236{ 237 void *headers_c = spec->match_criteria, *headers_v = spec->match_value, *fmask, *fval; 238 int soffset = mlx5e_tc_attr_to_reg_mappings[type].soffset; 239 int moffset = mlx5e_tc_attr_to_reg_mappings[type].moffset; 240 int match_len = mlx5e_tc_attr_to_reg_mappings[type].mlen; 241 u32 max_mask = GENMASK(match_len - 1, 0); 242 __be32 curr_mask_be, curr_val_be; 243 u32 curr_mask, curr_val; 244 245 fmask = headers_c + soffset; 246 fval = headers_v + soffset; 247 248 memcpy(&curr_mask_be, fmask, 4); 249 memcpy(&curr_val_be, fval, 4); 250 251 curr_mask = be32_to_cpu(curr_mask_be); 252 curr_val = be32_to_cpu(curr_val_be); 253 254 *mask = (curr_mask >> moffset) & max_mask; 255 *val = (curr_val >> moffset) & max_mask; 256} 257 258int 259mlx5e_tc_match_to_reg_set_and_get_id(struct mlx5_core_dev *mdev, 260 struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts, 261 enum mlx5_flow_namespace_type ns, 262 enum mlx5e_tc_attr_to_reg type, 263 u32 data) 264{ 265 int moffset = mlx5e_tc_attr_to_reg_mappings[type].moffset; 266 int mfield = mlx5e_tc_attr_to_reg_mappings[type].mfield; 267 int mlen = mlx5e_tc_attr_to_reg_mappings[type].mlen; 268 char *modact; 269 int err; 270 271 modact = mlx5e_mod_hdr_alloc(mdev, ns, mod_hdr_acts); 272 if (IS_ERR(modact)) 273 return PTR_ERR(modact); 274 275 /* Firmware has 5bit length field and 0 means 32bits */ 276 if (mlen == 32) 277 mlen = 0; 278 279 MLX5_SET(set_action_in, modact, action_type, MLX5_ACTION_TYPE_SET); 280 MLX5_SET(set_action_in, modact, field, mfield); 281 MLX5_SET(set_action_in, modact, offset, moffset); 282 MLX5_SET(set_action_in, modact, length, mlen); 283 MLX5_SET(set_action_in, modact, data, data); 284 err = mod_hdr_acts->num_actions; 285 mod_hdr_acts->num_actions++; 286 287 return err; 288} 289 290static struct mlx5e_tc_act_stats_handle * 291get_act_stats_handle(struct mlx5e_priv *priv) 292{ 293 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 294 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 295 struct mlx5_rep_uplink_priv *uplink_priv; 296 struct mlx5e_rep_priv *uplink_rpriv; 297 298 if (is_mdev_switchdev_mode(priv->mdev)) { 299 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 300 uplink_priv = &uplink_rpriv->uplink_priv; 301 302 return uplink_priv->action_stats_handle; 303 } 304 305 return tc->action_stats_handle; 306} 307 308struct mlx5e_tc_int_port_priv * 309mlx5e_get_int_port_priv(struct mlx5e_priv *priv) 310{ 311 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 312 struct mlx5_rep_uplink_priv *uplink_priv; 313 struct mlx5e_rep_priv *uplink_rpriv; 314 315 if (is_mdev_switchdev_mode(priv->mdev)) { 316 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 317 uplink_priv = &uplink_rpriv->uplink_priv; 318 319 return uplink_priv->int_port_priv; 320 } 321 322 return NULL; 323} 324 325struct mlx5e_flow_meters * 326mlx5e_get_flow_meters(struct mlx5_core_dev *dev) 327{ 328 struct mlx5_eswitch *esw = dev->priv.eswitch; 329 struct mlx5_rep_uplink_priv *uplink_priv; 330 struct mlx5e_rep_priv *uplink_rpriv; 331 struct mlx5e_priv *priv; 332 333 if (is_mdev_switchdev_mode(dev)) { 334 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 335 uplink_priv = &uplink_rpriv->uplink_priv; 336 priv = netdev_priv(uplink_rpriv->netdev); 337 if (!uplink_priv->flow_meters) 338 uplink_priv->flow_meters = 339 mlx5e_flow_meters_init(priv, 340 MLX5_FLOW_NAMESPACE_FDB, 341 uplink_priv->post_act); 342 if (!IS_ERR(uplink_priv->flow_meters)) 343 return uplink_priv->flow_meters; 344 } 345 346 return NULL; 347} 348 349static struct mlx5_tc_ct_priv * 350get_ct_priv(struct mlx5e_priv *priv) 351{ 352 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 353 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 354 struct mlx5_rep_uplink_priv *uplink_priv; 355 struct mlx5e_rep_priv *uplink_rpriv; 356 357 if (is_mdev_switchdev_mode(priv->mdev)) { 358 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 359 uplink_priv = &uplink_rpriv->uplink_priv; 360 361 return uplink_priv->ct_priv; 362 } 363 364 return tc->ct; 365} 366 367static struct mlx5e_tc_psample * 368get_sample_priv(struct mlx5e_priv *priv) 369{ 370 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 371 struct mlx5_rep_uplink_priv *uplink_priv; 372 struct mlx5e_rep_priv *uplink_rpriv; 373 374 if (is_mdev_switchdev_mode(priv->mdev)) { 375 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 376 uplink_priv = &uplink_rpriv->uplink_priv; 377 378 return uplink_priv->tc_psample; 379 } 380 381 return NULL; 382} 383 384static struct mlx5e_post_act * 385get_post_action(struct mlx5e_priv *priv) 386{ 387 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 388 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 389 struct mlx5_rep_uplink_priv *uplink_priv; 390 struct mlx5e_rep_priv *uplink_rpriv; 391 392 if (is_mdev_switchdev_mode(priv->mdev)) { 393 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 394 uplink_priv = &uplink_rpriv->uplink_priv; 395 396 return uplink_priv->post_act; 397 } 398 399 return tc->post_act; 400} 401 402struct mlx5_flow_handle * 403mlx5_tc_rule_insert(struct mlx5e_priv *priv, 404 struct mlx5_flow_spec *spec, 405 struct mlx5_flow_attr *attr) 406{ 407 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 408 409 if (is_mdev_switchdev_mode(priv->mdev)) 410 return mlx5_eswitch_add_offloaded_rule(esw, spec, attr); 411 412 return mlx5e_add_offloaded_nic_rule(priv, spec, attr); 413} 414 415void 416mlx5_tc_rule_delete(struct mlx5e_priv *priv, 417 struct mlx5_flow_handle *rule, 418 struct mlx5_flow_attr *attr) 419{ 420 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 421 422 if (is_mdev_switchdev_mode(priv->mdev)) { 423 mlx5_eswitch_del_offloaded_rule(esw, rule, attr); 424 return; 425 } 426 427 mlx5e_del_offloaded_nic_rule(priv, rule, attr); 428} 429 430static bool 431is_flow_meter_action(struct mlx5_flow_attr *attr) 432{ 433 return (((attr->action & MLX5_FLOW_CONTEXT_ACTION_EXECUTE_ASO) && 434 (attr->exe_aso_type == MLX5_EXE_ASO_FLOW_METER)) || 435 attr->flags & MLX5_ATTR_FLAG_MTU); 436} 437 438static int 439mlx5e_tc_add_flow_meter(struct mlx5e_priv *priv, 440 struct mlx5_flow_attr *attr) 441{ 442 struct mlx5e_post_act *post_act = get_post_action(priv); 443 struct mlx5e_post_meter_priv *post_meter; 444 enum mlx5_flow_namespace_type ns_type; 445 struct mlx5e_flow_meter_handle *meter; 446 enum mlx5e_post_meter_type type; 447 448 if (IS_ERR(post_act)) 449 return PTR_ERR(post_act); 450 451 meter = mlx5e_tc_meter_replace(priv->mdev, &attr->meter_attr.params); 452 if (IS_ERR(meter)) { 453 mlx5_core_err(priv->mdev, "Failed to get flow meter\n"); 454 return PTR_ERR(meter); 455 } 456 457 ns_type = mlx5e_tc_meter_get_namespace(meter->flow_meters); 458 type = meter->params.mtu ? MLX5E_POST_METER_MTU : MLX5E_POST_METER_RATE; 459 post_meter = mlx5e_post_meter_init(priv, ns_type, post_act, 460 type, 461 meter->act_counter, meter->drop_counter, 462 attr->branch_true, attr->branch_false); 463 if (IS_ERR(post_meter)) { 464 mlx5_core_err(priv->mdev, "Failed to init post meter\n"); 465 goto err_meter_init; 466 } 467 468 attr->meter_attr.meter = meter; 469 attr->meter_attr.post_meter = post_meter; 470 attr->dest_ft = mlx5e_post_meter_get_ft(post_meter); 471 attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 472 473 return 0; 474 475err_meter_init: 476 mlx5e_tc_meter_put(meter); 477 return PTR_ERR(post_meter); 478} 479 480static void 481mlx5e_tc_del_flow_meter(struct mlx5_eswitch *esw, struct mlx5_flow_attr *attr) 482{ 483 mlx5e_post_meter_cleanup(esw, attr->meter_attr.post_meter); 484 mlx5e_tc_meter_put(attr->meter_attr.meter); 485} 486 487struct mlx5_flow_handle * 488mlx5e_tc_rule_offload(struct mlx5e_priv *priv, 489 struct mlx5_flow_spec *spec, 490 struct mlx5_flow_attr *attr) 491{ 492 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 493 int err; 494 495 if (!is_mdev_switchdev_mode(priv->mdev)) 496 return mlx5e_add_offloaded_nic_rule(priv, spec, attr); 497 498 if (attr->flags & MLX5_ATTR_FLAG_SAMPLE) 499 return mlx5e_tc_sample_offload(get_sample_priv(priv), spec, attr); 500 501 if (is_flow_meter_action(attr)) { 502 err = mlx5e_tc_add_flow_meter(priv, attr); 503 if (err) 504 return ERR_PTR(err); 505 } 506 507 return mlx5_eswitch_add_offloaded_rule(esw, spec, attr); 508} 509 510void 511mlx5e_tc_rule_unoffload(struct mlx5e_priv *priv, 512 struct mlx5_flow_handle *rule, 513 struct mlx5_flow_attr *attr) 514{ 515 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 516 517 if (!is_mdev_switchdev_mode(priv->mdev)) { 518 mlx5e_del_offloaded_nic_rule(priv, rule, attr); 519 return; 520 } 521 522 if (attr->flags & MLX5_ATTR_FLAG_SAMPLE) { 523 mlx5e_tc_sample_unoffload(get_sample_priv(priv), rule, attr); 524 return; 525 } 526 527 mlx5_eswitch_del_offloaded_rule(esw, rule, attr); 528 529 if (attr->meter_attr.meter) 530 mlx5e_tc_del_flow_meter(esw, attr); 531} 532 533int 534mlx5e_tc_match_to_reg_set(struct mlx5_core_dev *mdev, 535 struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts, 536 enum mlx5_flow_namespace_type ns, 537 enum mlx5e_tc_attr_to_reg type, 538 u32 data) 539{ 540 int ret = mlx5e_tc_match_to_reg_set_and_get_id(mdev, mod_hdr_acts, ns, type, data); 541 542 return ret < 0 ? ret : 0; 543} 544 545void mlx5e_tc_match_to_reg_mod_hdr_change(struct mlx5_core_dev *mdev, 546 struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts, 547 enum mlx5e_tc_attr_to_reg type, 548 int act_id, u32 data) 549{ 550 int moffset = mlx5e_tc_attr_to_reg_mappings[type].moffset; 551 int mfield = mlx5e_tc_attr_to_reg_mappings[type].mfield; 552 int mlen = mlx5e_tc_attr_to_reg_mappings[type].mlen; 553 char *modact; 554 555 modact = mlx5e_mod_hdr_get_item(mod_hdr_acts, act_id); 556 557 /* Firmware has 5bit length field and 0 means 32bits */ 558 if (mlen == 32) 559 mlen = 0; 560 561 MLX5_SET(set_action_in, modact, action_type, MLX5_ACTION_TYPE_SET); 562 MLX5_SET(set_action_in, modact, field, mfield); 563 MLX5_SET(set_action_in, modact, offset, moffset); 564 MLX5_SET(set_action_in, modact, length, mlen); 565 MLX5_SET(set_action_in, modact, data, data); 566} 567 568struct mlx5e_hairpin { 569 struct mlx5_hairpin *pair; 570 571 struct mlx5_core_dev *func_mdev; 572 struct mlx5e_priv *func_priv; 573 u32 tdn; 574 struct mlx5e_tir direct_tir; 575 576 int num_channels; 577 u8 log_num_packets; 578 struct mlx5e_rqt indir_rqt; 579 struct mlx5e_tir indir_tir[MLX5E_NUM_INDIR_TIRS]; 580 struct mlx5_ttc_table *ttc; 581}; 582 583struct mlx5e_hairpin_entry { 584 /* a node of a hash table which keeps all the hairpin entries */ 585 struct hlist_node hairpin_hlist; 586 587 /* protects flows list */ 588 spinlock_t flows_lock; 589 /* flows sharing the same hairpin */ 590 struct list_head flows; 591 /* hpe's that were not fully initialized when dead peer update event 592 * function traversed them. 593 */ 594 struct list_head dead_peer_wait_list; 595 596 u16 peer_vhca_id; 597 u8 prio; 598 struct mlx5e_hairpin *hp; 599 refcount_t refcnt; 600 struct completion res_ready; 601}; 602 603static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, 604 struct mlx5e_tc_flow *flow); 605 606struct mlx5e_tc_flow *mlx5e_flow_get(struct mlx5e_tc_flow *flow) 607{ 608 if (!flow || !refcount_inc_not_zero(&flow->refcnt)) 609 return ERR_PTR(-EINVAL); 610 return flow; 611} 612 613void mlx5e_flow_put(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow) 614{ 615 if (refcount_dec_and_test(&flow->refcnt)) { 616 mlx5e_tc_del_flow(priv, flow); 617 kfree_rcu(flow, rcu_head); 618 } 619} 620 621bool mlx5e_is_eswitch_flow(struct mlx5e_tc_flow *flow) 622{ 623 return flow_flag_test(flow, ESWITCH); 624} 625 626bool mlx5e_is_ft_flow(struct mlx5e_tc_flow *flow) 627{ 628 return flow_flag_test(flow, FT); 629} 630 631bool mlx5e_is_offloaded_flow(struct mlx5e_tc_flow *flow) 632{ 633 return flow_flag_test(flow, OFFLOADED); 634} 635 636int mlx5e_get_flow_namespace(struct mlx5e_tc_flow *flow) 637{ 638 return mlx5e_is_eswitch_flow(flow) ? 639 MLX5_FLOW_NAMESPACE_FDB : MLX5_FLOW_NAMESPACE_KERNEL; 640} 641 642static struct mlx5_core_dev * 643get_flow_counter_dev(struct mlx5e_tc_flow *flow) 644{ 645 return mlx5e_is_eswitch_flow(flow) ? flow->attr->esw_attr->counter_dev : flow->priv->mdev; 646} 647 648static struct mod_hdr_tbl * 649get_mod_hdr_table(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow) 650{ 651 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 652 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 653 654 return mlx5e_get_flow_namespace(flow) == MLX5_FLOW_NAMESPACE_FDB ? 655 &esw->offloads.mod_hdr : 656 &tc->mod_hdr; 657} 658 659int mlx5e_tc_attach_mod_hdr(struct mlx5e_priv *priv, 660 struct mlx5e_tc_flow *flow, 661 struct mlx5_flow_attr *attr) 662{ 663 struct mlx5e_mod_hdr_handle *mh; 664 665 mh = mlx5e_mod_hdr_attach(priv->mdev, get_mod_hdr_table(priv, flow), 666 mlx5e_get_flow_namespace(flow), 667 &attr->parse_attr->mod_hdr_acts); 668 if (IS_ERR(mh)) 669 return PTR_ERR(mh); 670 671 WARN_ON(attr->modify_hdr); 672 attr->modify_hdr = mlx5e_mod_hdr_get(mh); 673 attr->mh = mh; 674 675 return 0; 676} 677 678void mlx5e_tc_detach_mod_hdr(struct mlx5e_priv *priv, 679 struct mlx5e_tc_flow *flow, 680 struct mlx5_flow_attr *attr) 681{ 682 /* flow wasn't fully initialized */ 683 if (!attr->mh) 684 return; 685 686 mlx5e_mod_hdr_detach(priv->mdev, get_mod_hdr_table(priv, flow), 687 attr->mh); 688 attr->mh = NULL; 689} 690 691static 692struct mlx5_core_dev *mlx5e_hairpin_get_mdev(struct net *net, int ifindex) 693{ 694 struct mlx5_core_dev *mdev; 695 struct net_device *netdev; 696 struct mlx5e_priv *priv; 697 698 netdev = dev_get_by_index(net, ifindex); 699 if (!netdev) 700 return ERR_PTR(-ENODEV); 701 702 priv = netdev_priv(netdev); 703 mdev = priv->mdev; 704 dev_put(netdev); 705 706 /* Mirred tc action holds a refcount on the ifindex net_device (see 707 * net/sched/act_mirred.c:tcf_mirred_get_dev). So, it's okay to continue using mdev 708 * after dev_put(netdev), while we're in the context of adding a tc flow. 709 * 710 * The mdev pointer corresponds to the peer/out net_device of a hairpin. It is then 711 * stored in a hairpin object, which exists until all flows, that refer to it, get 712 * removed. 713 * 714 * On the other hand, after a hairpin object has been created, the peer net_device may 715 * be removed/unbound while there are still some hairpin flows that are using it. This 716 * case is handled by mlx5e_tc_hairpin_update_dead_peer, which is hooked to 717 * NETDEV_UNREGISTER event of the peer net_device. 718 */ 719 return mdev; 720} 721 722static int mlx5e_hairpin_create_transport(struct mlx5e_hairpin *hp) 723{ 724 struct mlx5e_tir_builder *builder; 725 int err; 726 727 builder = mlx5e_tir_builder_alloc(false); 728 if (!builder) 729 return -ENOMEM; 730 731 err = mlx5_core_alloc_transport_domain(hp->func_mdev, &hp->tdn); 732 if (err) 733 goto out; 734 735 mlx5e_tir_builder_build_inline(builder, hp->tdn, hp->pair->rqn[0]); 736 err = mlx5e_tir_init(&hp->direct_tir, builder, hp->func_mdev, false); 737 if (err) 738 goto create_tir_err; 739 740out: 741 mlx5e_tir_builder_free(builder); 742 return err; 743 744create_tir_err: 745 mlx5_core_dealloc_transport_domain(hp->func_mdev, hp->tdn); 746 747 goto out; 748} 749 750static void mlx5e_hairpin_destroy_transport(struct mlx5e_hairpin *hp) 751{ 752 mlx5e_tir_destroy(&hp->direct_tir); 753 mlx5_core_dealloc_transport_domain(hp->func_mdev, hp->tdn); 754} 755 756static int mlx5e_hairpin_create_indirect_rqt(struct mlx5e_hairpin *hp) 757{ 758 struct mlx5e_priv *priv = hp->func_priv; 759 struct mlx5_core_dev *mdev = priv->mdev; 760 struct mlx5e_rss_params_indir indir; 761 u32 rqt_size; 762 int err; 763 764 rqt_size = mlx5e_rqt_size(mdev, hp->num_channels); 765 err = mlx5e_rss_params_indir_init(&indir, rqt_size, rqt_size); 766 if (err) 767 return err; 768 769 mlx5e_rss_params_indir_init_uniform(&indir, hp->num_channels); 770 err = mlx5e_rqt_init_indir(&hp->indir_rqt, mdev, hp->pair->rqn, NULL, hp->num_channels, 771 mlx5e_rx_res_get_current_hash(priv->rx_res).hfunc, 772 &indir); 773 774 mlx5e_rss_params_indir_cleanup(&indir); 775 return err; 776} 777 778static int mlx5e_hairpin_create_indirect_tirs(struct mlx5e_hairpin *hp) 779{ 780 struct mlx5e_priv *priv = hp->func_priv; 781 struct mlx5e_rss_params_hash rss_hash; 782 enum mlx5_traffic_types tt, max_tt; 783 struct mlx5e_tir_builder *builder; 784 int err = 0; 785 786 builder = mlx5e_tir_builder_alloc(false); 787 if (!builder) 788 return -ENOMEM; 789 790 rss_hash = mlx5e_rx_res_get_current_hash(priv->rx_res); 791 792 for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) { 793 struct mlx5e_rss_params_traffic_type rss_tt; 794 795 rss_tt = mlx5e_rss_get_default_tt_config(tt); 796 797 mlx5e_tir_builder_build_rqt(builder, hp->tdn, 798 mlx5e_rqt_get_rqtn(&hp->indir_rqt), 799 false); 800 mlx5e_tir_builder_build_rss(builder, &rss_hash, &rss_tt, false); 801 802 err = mlx5e_tir_init(&hp->indir_tir[tt], builder, hp->func_mdev, false); 803 if (err) { 804 mlx5_core_warn(hp->func_mdev, "create indirect tirs failed, %d\n", err); 805 goto err_destroy_tirs; 806 } 807 808 mlx5e_tir_builder_clear(builder); 809 } 810 811out: 812 mlx5e_tir_builder_free(builder); 813 return err; 814 815err_destroy_tirs: 816 max_tt = tt; 817 for (tt = 0; tt < max_tt; tt++) 818 mlx5e_tir_destroy(&hp->indir_tir[tt]); 819 820 goto out; 821} 822 823static void mlx5e_hairpin_destroy_indirect_tirs(struct mlx5e_hairpin *hp) 824{ 825 int tt; 826 827 for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) 828 mlx5e_tir_destroy(&hp->indir_tir[tt]); 829} 830 831static void mlx5e_hairpin_set_ttc_params(struct mlx5e_hairpin *hp, 832 struct ttc_params *ttc_params) 833{ 834 struct mlx5_flow_table_attr *ft_attr = &ttc_params->ft_attr; 835 int tt; 836 837 memset(ttc_params, 0, sizeof(*ttc_params)); 838 839 ttc_params->ns_type = MLX5_FLOW_NAMESPACE_KERNEL; 840 for (tt = 0; tt < MLX5_NUM_TT; tt++) { 841 if (mlx5_ttc_is_decrypted_esp_tt(tt)) 842 continue; 843 844 ttc_params->dests[tt].type = MLX5_FLOW_DESTINATION_TYPE_TIR; 845 ttc_params->dests[tt].tir_num = 846 tt == MLX5_TT_ANY ? 847 mlx5e_tir_get_tirn(&hp->direct_tir) : 848 mlx5e_tir_get_tirn(&hp->indir_tir[tt]); 849 } 850 851 ft_attr->level = MLX5E_TC_TTC_FT_LEVEL; 852 ft_attr->prio = MLX5E_TC_PRIO; 853} 854 855static int mlx5e_hairpin_rss_init(struct mlx5e_hairpin *hp) 856{ 857 struct mlx5e_priv *priv = hp->func_priv; 858 struct ttc_params ttc_params; 859 struct mlx5_ttc_table *ttc; 860 int err; 861 862 err = mlx5e_hairpin_create_indirect_rqt(hp); 863 if (err) 864 return err; 865 866 err = mlx5e_hairpin_create_indirect_tirs(hp); 867 if (err) 868 goto err_create_indirect_tirs; 869 870 mlx5e_hairpin_set_ttc_params(hp, &ttc_params); 871 hp->ttc = mlx5_create_ttc_table(priv->mdev, &ttc_params); 872 if (IS_ERR(hp->ttc)) { 873 err = PTR_ERR(hp->ttc); 874 goto err_create_ttc_table; 875 } 876 877 ttc = mlx5e_fs_get_ttc(priv->fs, false); 878 netdev_dbg(priv->netdev, "add hairpin: using %d channels rss ttc table id %x\n", 879 hp->num_channels, 880 mlx5_get_ttc_flow_table(ttc)->id); 881 882 return 0; 883 884err_create_ttc_table: 885 mlx5e_hairpin_destroy_indirect_tirs(hp); 886err_create_indirect_tirs: 887 mlx5e_rqt_destroy(&hp->indir_rqt); 888 889 return err; 890} 891 892static void mlx5e_hairpin_rss_cleanup(struct mlx5e_hairpin *hp) 893{ 894 mlx5_destroy_ttc_table(hp->ttc); 895 mlx5e_hairpin_destroy_indirect_tirs(hp); 896 mlx5e_rqt_destroy(&hp->indir_rqt); 897} 898 899static struct mlx5e_hairpin * 900mlx5e_hairpin_create(struct mlx5e_priv *priv, struct mlx5_hairpin_params *params, 901 int peer_ifindex) 902{ 903 struct mlx5_core_dev *func_mdev, *peer_mdev; 904 struct mlx5e_hairpin *hp; 905 struct mlx5_hairpin *pair; 906 int err; 907 908 hp = kzalloc(sizeof(*hp), GFP_KERNEL); 909 if (!hp) 910 return ERR_PTR(-ENOMEM); 911 912 func_mdev = priv->mdev; 913 peer_mdev = mlx5e_hairpin_get_mdev(dev_net(priv->netdev), peer_ifindex); 914 if (IS_ERR(peer_mdev)) { 915 err = PTR_ERR(peer_mdev); 916 goto create_pair_err; 917 } 918 919 pair = mlx5_core_hairpin_create(func_mdev, peer_mdev, params); 920 if (IS_ERR(pair)) { 921 err = PTR_ERR(pair); 922 goto create_pair_err; 923 } 924 hp->pair = pair; 925 hp->func_mdev = func_mdev; 926 hp->func_priv = priv; 927 hp->num_channels = params->num_channels; 928 hp->log_num_packets = params->log_num_packets; 929 930 err = mlx5e_hairpin_create_transport(hp); 931 if (err) 932 goto create_transport_err; 933 934 if (hp->num_channels > 1) { 935 err = mlx5e_hairpin_rss_init(hp); 936 if (err) 937 goto rss_init_err; 938 } 939 940 return hp; 941 942rss_init_err: 943 mlx5e_hairpin_destroy_transport(hp); 944create_transport_err: 945 mlx5_core_hairpin_destroy(hp->pair); 946create_pair_err: 947 kfree(hp); 948 return ERR_PTR(err); 949} 950 951static void mlx5e_hairpin_destroy(struct mlx5e_hairpin *hp) 952{ 953 if (hp->num_channels > 1) 954 mlx5e_hairpin_rss_cleanup(hp); 955 mlx5e_hairpin_destroy_transport(hp); 956 mlx5_core_hairpin_destroy(hp->pair); 957 kvfree(hp); 958} 959 960static inline u32 hash_hairpin_info(u16 peer_vhca_id, u8 prio) 961{ 962 return (peer_vhca_id << 16 | prio); 963} 964 965static struct mlx5e_hairpin_entry *mlx5e_hairpin_get(struct mlx5e_priv *priv, 966 u16 peer_vhca_id, u8 prio) 967{ 968 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 969 struct mlx5e_hairpin_entry *hpe; 970 u32 hash_key = hash_hairpin_info(peer_vhca_id, prio); 971 972 hash_for_each_possible(tc->hairpin_tbl, hpe, 973 hairpin_hlist, hash_key) { 974 if (hpe->peer_vhca_id == peer_vhca_id && hpe->prio == prio) { 975 refcount_inc(&hpe->refcnt); 976 return hpe; 977 } 978 } 979 980 return NULL; 981} 982 983static void mlx5e_hairpin_put(struct mlx5e_priv *priv, 984 struct mlx5e_hairpin_entry *hpe) 985{ 986 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 987 /* no more hairpin flows for us, release the hairpin pair */ 988 if (!refcount_dec_and_mutex_lock(&hpe->refcnt, &tc->hairpin_tbl_lock)) 989 return; 990 hash_del(&hpe->hairpin_hlist); 991 mutex_unlock(&tc->hairpin_tbl_lock); 992 993 if (!IS_ERR_OR_NULL(hpe->hp)) { 994 netdev_dbg(priv->netdev, "del hairpin: peer %s\n", 995 dev_name(hpe->hp->pair->peer_mdev->device)); 996 997 mlx5e_hairpin_destroy(hpe->hp); 998 } 999 1000 WARN_ON(!list_empty(&hpe->flows)); 1001 kfree(hpe); 1002} 1003 1004#define UNKNOWN_MATCH_PRIO 8 1005 1006static int mlx5e_hairpin_get_prio(struct mlx5e_priv *priv, 1007 struct mlx5_flow_spec *spec, u8 *match_prio, 1008 struct netlink_ext_ack *extack) 1009{ 1010 void *headers_c, *headers_v; 1011 u8 prio_val, prio_mask = 0; 1012 bool vlan_present; 1013 1014#ifdef CONFIG_MLX5_CORE_EN_DCB 1015 if (priv->dcbx_dp.trust_state != MLX5_QPTS_TRUST_PCP) { 1016 NL_SET_ERR_MSG_MOD(extack, 1017 "only PCP trust state supported for hairpin"); 1018 return -EOPNOTSUPP; 1019 } 1020#endif 1021 headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, outer_headers); 1022 headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers); 1023 1024 vlan_present = MLX5_GET(fte_match_set_lyr_2_4, headers_v, cvlan_tag); 1025 if (vlan_present) { 1026 prio_mask = MLX5_GET(fte_match_set_lyr_2_4, headers_c, first_prio); 1027 prio_val = MLX5_GET(fte_match_set_lyr_2_4, headers_v, first_prio); 1028 } 1029 1030 if (!vlan_present || !prio_mask) { 1031 prio_val = UNKNOWN_MATCH_PRIO; 1032 } else if (prio_mask != 0x7) { 1033 NL_SET_ERR_MSG_MOD(extack, 1034 "masked priority match not supported for hairpin"); 1035 return -EOPNOTSUPP; 1036 } 1037 1038 *match_prio = prio_val; 1039 return 0; 1040} 1041 1042static int debugfs_hairpin_num_active_get(void *data, u64 *val) 1043{ 1044 struct mlx5e_tc_table *tc = data; 1045 struct mlx5e_hairpin_entry *hpe; 1046 u32 cnt = 0; 1047 u32 bkt; 1048 1049 mutex_lock(&tc->hairpin_tbl_lock); 1050 hash_for_each(tc->hairpin_tbl, bkt, hpe, hairpin_hlist) 1051 cnt++; 1052 mutex_unlock(&tc->hairpin_tbl_lock); 1053 1054 *val = cnt; 1055 1056 return 0; 1057} 1058DEFINE_DEBUGFS_ATTRIBUTE(fops_hairpin_num_active, 1059 debugfs_hairpin_num_active_get, NULL, "%llu\n"); 1060 1061static int debugfs_hairpin_table_dump_show(struct seq_file *file, void *priv) 1062 1063{ 1064 struct mlx5e_tc_table *tc = file->private; 1065 struct mlx5e_hairpin_entry *hpe; 1066 u32 bkt; 1067 1068 mutex_lock(&tc->hairpin_tbl_lock); 1069 hash_for_each(tc->hairpin_tbl, bkt, hpe, hairpin_hlist) 1070 seq_printf(file, 1071 "Hairpin peer_vhca_id %u prio %u refcnt %u num_channels %u num_packets %lu\n", 1072 hpe->peer_vhca_id, hpe->prio, 1073 refcount_read(&hpe->refcnt), hpe->hp->num_channels, 1074 BIT(hpe->hp->log_num_packets)); 1075 mutex_unlock(&tc->hairpin_tbl_lock); 1076 1077 return 0; 1078} 1079DEFINE_SHOW_ATTRIBUTE(debugfs_hairpin_table_dump); 1080 1081static void mlx5e_tc_debugfs_init(struct mlx5e_tc_table *tc, 1082 struct dentry *dfs_root) 1083{ 1084 if (IS_ERR_OR_NULL(dfs_root)) 1085 return; 1086 1087 tc->dfs_root = debugfs_create_dir("tc", dfs_root); 1088 1089 debugfs_create_file("hairpin_num_active", 0444, tc->dfs_root, tc, 1090 &fops_hairpin_num_active); 1091 debugfs_create_file("hairpin_table_dump", 0444, tc->dfs_root, tc, 1092 &debugfs_hairpin_table_dump_fops); 1093} 1094 1095static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, 1096 struct mlx5e_tc_flow *flow, 1097 struct mlx5e_tc_flow_parse_attr *parse_attr, 1098 struct netlink_ext_ack *extack) 1099{ 1100 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 1101 struct devlink *devlink = priv_to_devlink(priv->mdev); 1102 int peer_ifindex = parse_attr->mirred_ifindex[0]; 1103 union devlink_param_value val = {}; 1104 struct mlx5_hairpin_params params; 1105 struct mlx5_core_dev *peer_mdev; 1106 struct mlx5e_hairpin_entry *hpe; 1107 struct mlx5e_hairpin *hp; 1108 u8 match_prio; 1109 u16 peer_id; 1110 int err; 1111 1112 peer_mdev = mlx5e_hairpin_get_mdev(dev_net(priv->netdev), peer_ifindex); 1113 if (IS_ERR(peer_mdev)) { 1114 NL_SET_ERR_MSG_MOD(extack, "invalid ifindex of mirred device"); 1115 return PTR_ERR(peer_mdev); 1116 } 1117 1118 if (!MLX5_CAP_GEN(priv->mdev, hairpin) || !MLX5_CAP_GEN(peer_mdev, hairpin)) { 1119 NL_SET_ERR_MSG_MOD(extack, "hairpin is not supported"); 1120 return -EOPNOTSUPP; 1121 } 1122 1123 peer_id = MLX5_CAP_GEN(peer_mdev, vhca_id); 1124 err = mlx5e_hairpin_get_prio(priv, &parse_attr->spec, &match_prio, 1125 extack); 1126 if (err) 1127 return err; 1128 1129 mutex_lock(&tc->hairpin_tbl_lock); 1130 hpe = mlx5e_hairpin_get(priv, peer_id, match_prio); 1131 if (hpe) { 1132 mutex_unlock(&tc->hairpin_tbl_lock); 1133 wait_for_completion(&hpe->res_ready); 1134 1135 if (IS_ERR(hpe->hp)) { 1136 err = -EREMOTEIO; 1137 goto out_err; 1138 } 1139 goto attach_flow; 1140 } 1141 1142 hpe = kzalloc(sizeof(*hpe), GFP_KERNEL); 1143 if (!hpe) { 1144 mutex_unlock(&tc->hairpin_tbl_lock); 1145 return -ENOMEM; 1146 } 1147 1148 spin_lock_init(&hpe->flows_lock); 1149 INIT_LIST_HEAD(&hpe->flows); 1150 INIT_LIST_HEAD(&hpe->dead_peer_wait_list); 1151 hpe->peer_vhca_id = peer_id; 1152 hpe->prio = match_prio; 1153 refcount_set(&hpe->refcnt, 1); 1154 init_completion(&hpe->res_ready); 1155 1156 hash_add(tc->hairpin_tbl, &hpe->hairpin_hlist, 1157 hash_hairpin_info(peer_id, match_prio)); 1158 mutex_unlock(&tc->hairpin_tbl_lock); 1159 1160 err = devl_param_driverinit_value_get( 1161 devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_QUEUE_SIZE, &val); 1162 if (err) { 1163 err = -ENOMEM; 1164 goto out_err; 1165 } 1166 1167 params.log_num_packets = ilog2(val.vu32); 1168 params.log_data_size = 1169 clamp_t(u32, 1170 params.log_num_packets + 1171 MLX5_MPWRQ_MIN_LOG_STRIDE_SZ(priv->mdev), 1172 MLX5_CAP_GEN(priv->mdev, log_min_hairpin_wq_data_sz), 1173 MLX5_CAP_GEN(priv->mdev, log_max_hairpin_wq_data_sz)); 1174 1175 params.q_counter = priv->q_counter[0]; 1176 err = devl_param_driverinit_value_get( 1177 devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_NUM_QUEUES, &val); 1178 if (err) { 1179 err = -ENOMEM; 1180 goto out_err; 1181 } 1182 1183 params.num_channels = val.vu32; 1184 1185 hp = mlx5e_hairpin_create(priv, ¶ms, peer_ifindex); 1186 hpe->hp = hp; 1187 complete_all(&hpe->res_ready); 1188 if (IS_ERR(hp)) { 1189 err = PTR_ERR(hp); 1190 goto out_err; 1191 } 1192 1193 netdev_dbg(priv->netdev, "add hairpin: tirn %x rqn %x peer %s sqn %x prio %d (log) data %d packets %d\n", 1194 mlx5e_tir_get_tirn(&hp->direct_tir), hp->pair->rqn[0], 1195 dev_name(hp->pair->peer_mdev->device), 1196 hp->pair->sqn[0], match_prio, params.log_data_size, params.log_num_packets); 1197 1198attach_flow: 1199 if (hpe->hp->num_channels > 1) { 1200 flow_flag_set(flow, HAIRPIN_RSS); 1201 flow->attr->nic_attr->hairpin_ft = 1202 mlx5_get_ttc_flow_table(hpe->hp->ttc); 1203 } else { 1204 flow->attr->nic_attr->hairpin_tirn = mlx5e_tir_get_tirn(&hpe->hp->direct_tir); 1205 } 1206 1207 flow->hpe = hpe; 1208 spin_lock(&hpe->flows_lock); 1209 list_add(&flow->hairpin, &hpe->flows); 1210 spin_unlock(&hpe->flows_lock); 1211 1212 return 0; 1213 1214out_err: 1215 mlx5e_hairpin_put(priv, hpe); 1216 return err; 1217} 1218 1219static void mlx5e_hairpin_flow_del(struct mlx5e_priv *priv, 1220 struct mlx5e_tc_flow *flow) 1221{ 1222 /* flow wasn't fully initialized */ 1223 if (!flow->hpe) 1224 return; 1225 1226 spin_lock(&flow->hpe->flows_lock); 1227 list_del(&flow->hairpin); 1228 spin_unlock(&flow->hpe->flows_lock); 1229 1230 mlx5e_hairpin_put(priv, flow->hpe); 1231 flow->hpe = NULL; 1232} 1233 1234struct mlx5_flow_handle * 1235mlx5e_add_offloaded_nic_rule(struct mlx5e_priv *priv, 1236 struct mlx5_flow_spec *spec, 1237 struct mlx5_flow_attr *attr) 1238{ 1239 struct mlx5_flow_context *flow_context = &spec->flow_context; 1240 struct mlx5e_vlan_table *vlan = mlx5e_fs_get_vlan(priv->fs); 1241 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 1242 struct mlx5_nic_flow_attr *nic_attr = attr->nic_attr; 1243 struct mlx5_flow_destination dest[2] = {}; 1244 struct mlx5_fs_chains *nic_chains; 1245 struct mlx5_flow_act flow_act = { 1246 .action = attr->action, 1247 .flags = FLOW_ACT_NO_APPEND, 1248 }; 1249 struct mlx5_flow_handle *rule; 1250 struct mlx5_flow_table *ft; 1251 int dest_ix = 0; 1252 1253 nic_chains = mlx5e_nic_chains(tc); 1254 flow_context->flags |= FLOW_CONTEXT_HAS_TAG; 1255 flow_context->flow_tag = nic_attr->flow_tag; 1256 1257 if (attr->dest_ft) { 1258 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 1259 dest[dest_ix].ft = attr->dest_ft; 1260 dest_ix++; 1261 } else if (nic_attr->hairpin_ft) { 1262 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 1263 dest[dest_ix].ft = nic_attr->hairpin_ft; 1264 dest_ix++; 1265 } else if (nic_attr->hairpin_tirn) { 1266 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_TIR; 1267 dest[dest_ix].tir_num = nic_attr->hairpin_tirn; 1268 dest_ix++; 1269 } else if (attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { 1270 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 1271 if (attr->dest_chain) { 1272 dest[dest_ix].ft = mlx5_chains_get_table(nic_chains, 1273 attr->dest_chain, 1, 1274 MLX5E_TC_FT_LEVEL); 1275 if (IS_ERR(dest[dest_ix].ft)) 1276 return ERR_CAST(dest[dest_ix].ft); 1277 } else { 1278 dest[dest_ix].ft = mlx5e_vlan_get_flowtable(vlan); 1279 } 1280 dest_ix++; 1281 } 1282 1283 if (dest[0].type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE && 1284 MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, ignore_flow_level)) 1285 flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL; 1286 1287 if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { 1288 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; 1289 dest[dest_ix].counter = attr->counter; 1290 dest_ix++; 1291 } 1292 1293 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) 1294 flow_act.modify_hdr = attr->modify_hdr; 1295 1296 mutex_lock(&tc->t_lock); 1297 if (IS_ERR_OR_NULL(tc->t)) { 1298 /* Create the root table here if doesn't exist yet */ 1299 tc->t = 1300 mlx5_chains_get_table(nic_chains, 0, 1, MLX5E_TC_FT_LEVEL); 1301 1302 if (IS_ERR(tc->t)) { 1303 mutex_unlock(&tc->t_lock); 1304 netdev_err(priv->netdev, 1305 "Failed to create tc offload table\n"); 1306 rule = ERR_CAST(tc->t); 1307 goto err_ft_get; 1308 } 1309 } 1310 mutex_unlock(&tc->t_lock); 1311 1312 if (attr->chain || attr->prio) 1313 ft = mlx5_chains_get_table(nic_chains, 1314 attr->chain, attr->prio, 1315 MLX5E_TC_FT_LEVEL); 1316 else 1317 ft = attr->ft; 1318 1319 if (IS_ERR(ft)) { 1320 rule = ERR_CAST(ft); 1321 goto err_ft_get; 1322 } 1323 1324 if (attr->outer_match_level != MLX5_MATCH_NONE) 1325 spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS; 1326 1327 rule = mlx5_add_flow_rules(ft, spec, 1328 &flow_act, dest, dest_ix); 1329 if (IS_ERR(rule)) 1330 goto err_rule; 1331 1332 return rule; 1333 1334err_rule: 1335 if (attr->chain || attr->prio) 1336 mlx5_chains_put_table(nic_chains, 1337 attr->chain, attr->prio, 1338 MLX5E_TC_FT_LEVEL); 1339err_ft_get: 1340 if (attr->dest_chain) 1341 mlx5_chains_put_table(nic_chains, 1342 attr->dest_chain, 1, 1343 MLX5E_TC_FT_LEVEL); 1344 1345 return ERR_CAST(rule); 1346} 1347 1348static int 1349alloc_flow_attr_counter(struct mlx5_core_dev *counter_dev, 1350 struct mlx5_flow_attr *attr) 1351 1352{ 1353 struct mlx5_fc *counter; 1354 1355 counter = mlx5_fc_create(counter_dev, true); 1356 if (IS_ERR(counter)) 1357 return PTR_ERR(counter); 1358 1359 attr->counter = counter; 1360 return 0; 1361} 1362 1363static int 1364mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, 1365 struct mlx5e_tc_flow *flow, 1366 struct netlink_ext_ack *extack) 1367{ 1368 struct mlx5e_tc_flow_parse_attr *parse_attr; 1369 struct mlx5_flow_attr *attr = flow->attr; 1370 struct mlx5_core_dev *dev = priv->mdev; 1371 int err; 1372 1373 parse_attr = attr->parse_attr; 1374 1375 if (flow_flag_test(flow, HAIRPIN)) { 1376 err = mlx5e_hairpin_flow_add(priv, flow, parse_attr, extack); 1377 if (err) 1378 return err; 1379 } 1380 1381 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { 1382 err = alloc_flow_attr_counter(dev, attr); 1383 if (err) 1384 return err; 1385 } 1386 1387 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { 1388 err = mlx5e_tc_attach_mod_hdr(priv, flow, attr); 1389 if (err) 1390 return err; 1391 } 1392 1393 flow->rule[0] = mlx5e_add_offloaded_nic_rule(priv, &parse_attr->spec, attr); 1394 return PTR_ERR_OR_ZERO(flow->rule[0]); 1395} 1396 1397void mlx5e_del_offloaded_nic_rule(struct mlx5e_priv *priv, 1398 struct mlx5_flow_handle *rule, 1399 struct mlx5_flow_attr *attr) 1400{ 1401 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 1402 struct mlx5_fs_chains *nic_chains; 1403 1404 nic_chains = mlx5e_nic_chains(tc); 1405 mlx5_del_flow_rules(rule); 1406 1407 if (attr->chain || attr->prio) 1408 mlx5_chains_put_table(nic_chains, attr->chain, attr->prio, 1409 MLX5E_TC_FT_LEVEL); 1410 1411 if (attr->dest_chain) 1412 mlx5_chains_put_table(nic_chains, attr->dest_chain, 1, 1413 MLX5E_TC_FT_LEVEL); 1414} 1415 1416static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv, 1417 struct mlx5e_tc_flow *flow) 1418{ 1419 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 1420 struct mlx5_flow_attr *attr = flow->attr; 1421 1422 flow_flag_clear(flow, OFFLOADED); 1423 1424 if (!IS_ERR_OR_NULL(flow->rule[0])) 1425 mlx5e_del_offloaded_nic_rule(priv, flow->rule[0], attr); 1426 1427 /* Remove root table if no rules are left to avoid 1428 * extra steering hops. 1429 */ 1430 mutex_lock(&tc->t_lock); 1431 if (!mlx5e_tc_num_filters(priv, MLX5_TC_FLAG(NIC_OFFLOAD)) && 1432 !IS_ERR_OR_NULL(tc->t)) { 1433 mlx5_chains_put_table(mlx5e_nic_chains(tc), 0, 1, MLX5E_TC_FT_LEVEL); 1434 tc->t = NULL; 1435 } 1436 mutex_unlock(&tc->t_lock); 1437 1438 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { 1439 mlx5e_mod_hdr_dealloc(&attr->parse_attr->mod_hdr_acts); 1440 mlx5e_tc_detach_mod_hdr(priv, flow, attr); 1441 } 1442 1443 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) 1444 mlx5_fc_destroy(priv->mdev, attr->counter); 1445 1446 if (flow_flag_test(flow, HAIRPIN)) 1447 mlx5e_hairpin_flow_del(priv, flow); 1448 1449 free_flow_post_acts(flow); 1450 mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), attr); 1451 1452 kvfree(attr->parse_attr); 1453 kfree(flow->attr); 1454} 1455 1456struct mlx5_flow_handle * 1457mlx5e_tc_offload_fdb_rules(struct mlx5_eswitch *esw, 1458 struct mlx5e_tc_flow *flow, 1459 struct mlx5_flow_spec *spec, 1460 struct mlx5_flow_attr *attr) 1461{ 1462 struct mlx5_flow_handle *rule; 1463 1464 if (attr->flags & MLX5_ATTR_FLAG_SLOW_PATH) 1465 return mlx5_eswitch_add_offloaded_rule(esw, spec, attr); 1466 1467 rule = mlx5e_tc_rule_offload(flow->priv, spec, attr); 1468 1469 if (IS_ERR(rule)) 1470 return rule; 1471 1472 if (attr->esw_attr->split_count) { 1473 flow->rule[1] = mlx5_eswitch_add_fwd_rule(esw, spec, attr); 1474 if (IS_ERR(flow->rule[1])) 1475 goto err_rule1; 1476 } 1477 1478 return rule; 1479 1480err_rule1: 1481 mlx5e_tc_rule_unoffload(flow->priv, rule, attr); 1482 return flow->rule[1]; 1483} 1484 1485void mlx5e_tc_unoffload_fdb_rules(struct mlx5_eswitch *esw, 1486 struct mlx5e_tc_flow *flow, 1487 struct mlx5_flow_attr *attr) 1488{ 1489 flow_flag_clear(flow, OFFLOADED); 1490 1491 if (attr->flags & MLX5_ATTR_FLAG_SLOW_PATH) 1492 return mlx5_eswitch_del_offloaded_rule(esw, flow->rule[0], attr); 1493 1494 if (attr->esw_attr->split_count) 1495 mlx5_eswitch_del_fwd_rule(esw, flow->rule[1], attr); 1496 1497 mlx5e_tc_rule_unoffload(flow->priv, flow->rule[0], attr); 1498} 1499 1500struct mlx5_flow_handle * 1501mlx5e_tc_offload_to_slow_path(struct mlx5_eswitch *esw, 1502 struct mlx5e_tc_flow *flow, 1503 struct mlx5_flow_spec *spec) 1504{ 1505 struct mlx5e_tc_mod_hdr_acts mod_acts = {}; 1506 struct mlx5e_mod_hdr_handle *mh = NULL; 1507 struct mlx5_flow_attr *slow_attr; 1508 struct mlx5_flow_handle *rule; 1509 bool fwd_and_modify_cap; 1510 u32 chain_mapping = 0; 1511 int err; 1512 1513 slow_attr = mlx5_alloc_flow_attr(MLX5_FLOW_NAMESPACE_FDB); 1514 if (!slow_attr) 1515 return ERR_PTR(-ENOMEM); 1516 1517 memcpy(slow_attr, flow->attr, ESW_FLOW_ATTR_SZ); 1518 slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 1519 slow_attr->esw_attr->split_count = 0; 1520 slow_attr->flags |= MLX5_ATTR_FLAG_SLOW_PATH; 1521 1522 fwd_and_modify_cap = MLX5_CAP_ESW_FLOWTABLE((esw)->dev, fdb_modify_header_fwd_to_table); 1523 if (!fwd_and_modify_cap) 1524 goto skip_restore; 1525 1526 err = mlx5_chains_get_chain_mapping(esw_chains(esw), flow->attr->chain, &chain_mapping); 1527 if (err) 1528 goto err_get_chain; 1529 1530 err = mlx5e_tc_match_to_reg_set(esw->dev, &mod_acts, MLX5_FLOW_NAMESPACE_FDB, 1531 MAPPED_OBJ_TO_REG, chain_mapping); 1532 if (err) 1533 goto err_reg_set; 1534 1535 mh = mlx5e_mod_hdr_attach(esw->dev, get_mod_hdr_table(flow->priv, flow), 1536 MLX5_FLOW_NAMESPACE_FDB, &mod_acts); 1537 if (IS_ERR(mh)) { 1538 err = PTR_ERR(mh); 1539 goto err_attach; 1540 } 1541 1542 slow_attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 1543 slow_attr->modify_hdr = mlx5e_mod_hdr_get(mh); 1544 1545skip_restore: 1546 rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, slow_attr); 1547 if (IS_ERR(rule)) { 1548 err = PTR_ERR(rule); 1549 goto err_offload; 1550 } 1551 1552 flow->attr->slow_mh = mh; 1553 flow->chain_mapping = chain_mapping; 1554 flow_flag_set(flow, SLOW); 1555 1556 mlx5e_mod_hdr_dealloc(&mod_acts); 1557 kfree(slow_attr); 1558 1559 return rule; 1560 1561err_offload: 1562 if (fwd_and_modify_cap) 1563 mlx5e_mod_hdr_detach(esw->dev, get_mod_hdr_table(flow->priv, flow), mh); 1564err_attach: 1565err_reg_set: 1566 if (fwd_and_modify_cap) 1567 mlx5_chains_put_chain_mapping(esw_chains(esw), chain_mapping); 1568err_get_chain: 1569 mlx5e_mod_hdr_dealloc(&mod_acts); 1570 kfree(slow_attr); 1571 return ERR_PTR(err); 1572} 1573 1574void mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw, 1575 struct mlx5e_tc_flow *flow) 1576{ 1577 struct mlx5e_mod_hdr_handle *slow_mh = flow->attr->slow_mh; 1578 struct mlx5_flow_attr *slow_attr; 1579 1580 slow_attr = mlx5_alloc_flow_attr(MLX5_FLOW_NAMESPACE_FDB); 1581 if (!slow_attr) { 1582 mlx5_core_warn(flow->priv->mdev, "Unable to alloc attr to unoffload slow path rule\n"); 1583 return; 1584 } 1585 1586 memcpy(slow_attr, flow->attr, ESW_FLOW_ATTR_SZ); 1587 slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 1588 slow_attr->esw_attr->split_count = 0; 1589 slow_attr->flags |= MLX5_ATTR_FLAG_SLOW_PATH; 1590 if (slow_mh) { 1591 slow_attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 1592 slow_attr->modify_hdr = mlx5e_mod_hdr_get(slow_mh); 1593 } 1594 mlx5e_tc_unoffload_fdb_rules(esw, flow, slow_attr); 1595 if (slow_mh) { 1596 mlx5e_mod_hdr_detach(esw->dev, get_mod_hdr_table(flow->priv, flow), slow_mh); 1597 mlx5_chains_put_chain_mapping(esw_chains(esw), flow->chain_mapping); 1598 flow->chain_mapping = 0; 1599 flow->attr->slow_mh = NULL; 1600 } 1601 flow_flag_clear(flow, SLOW); 1602 kfree(slow_attr); 1603} 1604 1605/* Caller must obtain uplink_priv->unready_flows_lock mutex before calling this 1606 * function. 1607 */ 1608static void unready_flow_add(struct mlx5e_tc_flow *flow, 1609 struct list_head *unready_flows) 1610{ 1611 flow_flag_set(flow, NOT_READY); 1612 list_add_tail(&flow->unready, unready_flows); 1613} 1614 1615/* Caller must obtain uplink_priv->unready_flows_lock mutex before calling this 1616 * function. 1617 */ 1618static void unready_flow_del(struct mlx5e_tc_flow *flow) 1619{ 1620 list_del(&flow->unready); 1621 flow_flag_clear(flow, NOT_READY); 1622} 1623 1624static void add_unready_flow(struct mlx5e_tc_flow *flow) 1625{ 1626 struct mlx5_rep_uplink_priv *uplink_priv; 1627 struct mlx5e_rep_priv *rpriv; 1628 struct mlx5_eswitch *esw; 1629 1630 esw = flow->priv->mdev->priv.eswitch; 1631 rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 1632 uplink_priv = &rpriv->uplink_priv; 1633 1634 mutex_lock(&uplink_priv->unready_flows_lock); 1635 unready_flow_add(flow, &uplink_priv->unready_flows); 1636 mutex_unlock(&uplink_priv->unready_flows_lock); 1637} 1638 1639static void remove_unready_flow(struct mlx5e_tc_flow *flow) 1640{ 1641 struct mlx5_rep_uplink_priv *uplink_priv; 1642 struct mlx5e_rep_priv *rpriv; 1643 struct mlx5_eswitch *esw; 1644 1645 esw = flow->priv->mdev->priv.eswitch; 1646 rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 1647 uplink_priv = &rpriv->uplink_priv; 1648 1649 mutex_lock(&uplink_priv->unready_flows_lock); 1650 if (flow_flag_test(flow, NOT_READY)) 1651 unready_flow_del(flow); 1652 mutex_unlock(&uplink_priv->unready_flows_lock); 1653} 1654 1655bool mlx5e_tc_is_vf_tunnel(struct net_device *out_dev, struct net_device *route_dev) 1656{ 1657 struct mlx5_core_dev *out_mdev, *route_mdev; 1658 struct mlx5e_priv *out_priv, *route_priv; 1659 1660 out_priv = netdev_priv(out_dev); 1661 out_mdev = out_priv->mdev; 1662 route_priv = netdev_priv(route_dev); 1663 route_mdev = route_priv->mdev; 1664 1665 if (out_mdev->coredev_type != MLX5_COREDEV_PF) 1666 return false; 1667 1668 if (route_mdev->coredev_type != MLX5_COREDEV_VF && 1669 route_mdev->coredev_type != MLX5_COREDEV_SF) 1670 return false; 1671 1672 return mlx5e_same_hw_devs(out_priv, route_priv); 1673} 1674 1675int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *route_dev, u16 *vport) 1676{ 1677 struct mlx5e_priv *out_priv, *route_priv; 1678 struct mlx5_core_dev *route_mdev; 1679 struct mlx5_devcom_comp_dev *pos; 1680 struct mlx5_eswitch *esw; 1681 u16 vhca_id; 1682 int err; 1683 1684 out_priv = netdev_priv(out_dev); 1685 esw = out_priv->mdev->priv.eswitch; 1686 route_priv = netdev_priv(route_dev); 1687 route_mdev = route_priv->mdev; 1688 1689 vhca_id = MLX5_CAP_GEN(route_mdev, vhca_id); 1690 err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); 1691 if (!err) 1692 return err; 1693 1694 if (!mlx5_lag_is_active(out_priv->mdev)) 1695 return err; 1696 1697 rcu_read_lock(); 1698 err = -ENODEV; 1699 mlx5_devcom_for_each_peer_entry_rcu(esw->devcom, esw, pos) { 1700 err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); 1701 if (!err) 1702 break; 1703 } 1704 rcu_read_unlock(); 1705 1706 return err; 1707} 1708 1709static int 1710verify_attr_actions(u32 actions, struct netlink_ext_ack *extack) 1711{ 1712 if (!(actions & 1713 (MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP))) { 1714 NL_SET_ERR_MSG_MOD(extack, "Rule must have at least one forward/drop action"); 1715 return -EOPNOTSUPP; 1716 } 1717 1718 if (!(~actions & 1719 (MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP))) { 1720 NL_SET_ERR_MSG_MOD(extack, "Rule cannot support forward+drop action"); 1721 return -EOPNOTSUPP; 1722 } 1723 1724 if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR && 1725 actions & MLX5_FLOW_CONTEXT_ACTION_DROP) { 1726 NL_SET_ERR_MSG_MOD(extack, "Drop with modify header action is not supported"); 1727 return -EOPNOTSUPP; 1728 } 1729 1730 return 0; 1731} 1732 1733static bool 1734has_encap_dests(struct mlx5_flow_attr *attr) 1735{ 1736 struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr; 1737 int out_index; 1738 1739 for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) 1740 if (esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP) 1741 return true; 1742 1743 return false; 1744} 1745 1746static int 1747extra_split_attr_dests_needed(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr) 1748{ 1749 bool int_dest = false, ext_dest = false; 1750 struct mlx5_esw_flow_attr *esw_attr; 1751 int i; 1752 1753 if (flow->attr != attr || 1754 !list_is_first(&attr->list, &flow->attrs)) 1755 return 0; 1756 1757 esw_attr = attr->esw_attr; 1758 if (!esw_attr->split_count || 1759 esw_attr->split_count == esw_attr->out_count - 1) 1760 return 0; 1761 1762 if (esw_attr->dest_int_port && 1763 (esw_attr->dests[esw_attr->split_count].flags & 1764 MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE)) 1765 return esw_attr->split_count + 1; 1766 1767 for (i = esw_attr->split_count; i < esw_attr->out_count; i++) { 1768 /* external dest with encap is considered as internal by firmware */ 1769 if (esw_attr->dests[i].vport == MLX5_VPORT_UPLINK && 1770 !(esw_attr->dests[i].flags & MLX5_ESW_DEST_ENCAP)) 1771 ext_dest = true; 1772 else 1773 int_dest = true; 1774 1775 if (ext_dest && int_dest) 1776 return esw_attr->split_count; 1777 } 1778 1779 return 0; 1780} 1781 1782static int 1783extra_split_attr_dests(struct mlx5e_tc_flow *flow, 1784 struct mlx5_flow_attr *attr, int split_count) 1785{ 1786 struct mlx5e_post_act *post_act = get_post_action(flow->priv); 1787 struct mlx5e_tc_flow_parse_attr *parse_attr, *parse_attr2; 1788 struct mlx5_esw_flow_attr *esw_attr, *esw_attr2; 1789 struct mlx5e_post_act_handle *handle; 1790 struct mlx5_flow_attr *attr2; 1791 int i, j, err; 1792 1793 if (IS_ERR(post_act)) 1794 return PTR_ERR(post_act); 1795 1796 attr2 = mlx5_alloc_flow_attr(mlx5e_get_flow_namespace(flow)); 1797 parse_attr2 = kvzalloc(sizeof(*parse_attr), GFP_KERNEL); 1798 if (!attr2 || !parse_attr2) { 1799 err = -ENOMEM; 1800 goto err_free; 1801 } 1802 attr2->parse_attr = parse_attr2; 1803 1804 handle = mlx5e_tc_post_act_add(post_act, attr2); 1805 if (IS_ERR(handle)) { 1806 err = PTR_ERR(handle); 1807 goto err_free; 1808 } 1809 1810 esw_attr = attr->esw_attr; 1811 esw_attr2 = attr2->esw_attr; 1812 esw_attr2->in_rep = esw_attr->in_rep; 1813 1814 parse_attr = attr->parse_attr; 1815 parse_attr2->filter_dev = parse_attr->filter_dev; 1816 1817 for (i = split_count, j = 0; i < esw_attr->out_count; i++, j++) 1818 esw_attr2->dests[j] = esw_attr->dests[i]; 1819 1820 esw_attr2->out_count = j; 1821 attr2->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 1822 1823 err = mlx5e_tc_post_act_offload(post_act, handle); 1824 if (err) 1825 goto err_post_act_offload; 1826 1827 err = mlx5e_tc_post_act_set_handle(flow->priv->mdev, handle, 1828 &parse_attr->mod_hdr_acts); 1829 if (err) 1830 goto err_post_act_set_handle; 1831 1832 esw_attr->out_count = split_count; 1833 attr->extra_split_ft = mlx5e_tc_post_act_get_ft(post_act); 1834 flow->extra_split_attr = attr2; 1835 1836 attr2->post_act_handle = handle; 1837 1838 return 0; 1839 1840err_post_act_set_handle: 1841 mlx5e_tc_post_act_unoffload(post_act, handle); 1842err_post_act_offload: 1843 mlx5e_tc_post_act_del(post_act, handle); 1844err_free: 1845 kvfree(parse_attr2); 1846 kfree(attr2); 1847 return err; 1848} 1849 1850static int 1851post_process_attr(struct mlx5e_tc_flow *flow, 1852 struct mlx5_flow_attr *attr, 1853 struct netlink_ext_ack *extack) 1854{ 1855 int extra_split; 1856 bool vf_tun; 1857 int err = 0; 1858 1859 err = verify_attr_actions(attr->action, extack); 1860 if (err) 1861 goto err_out; 1862 1863 if (mlx5e_is_eswitch_flow(flow) && has_encap_dests(attr)) { 1864 err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun); 1865 if (err) 1866 goto err_out; 1867 } 1868 1869 extra_split = extra_split_attr_dests_needed(flow, attr); 1870 if (extra_split > 0) { 1871 err = extra_split_attr_dests(flow, attr, extra_split); 1872 if (err) 1873 goto err_out; 1874 } 1875 1876 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { 1877 err = mlx5e_tc_attach_mod_hdr(flow->priv, flow, attr); 1878 if (err) 1879 goto err_out; 1880 } 1881 1882 if (attr->branch_true && 1883 attr->branch_true->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { 1884 err = mlx5e_tc_attach_mod_hdr(flow->priv, flow, attr->branch_true); 1885 if (err) 1886 goto err_out; 1887 } 1888 1889 if (attr->branch_false && 1890 attr->branch_false->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { 1891 err = mlx5e_tc_attach_mod_hdr(flow->priv, flow, attr->branch_false); 1892 if (err) 1893 goto err_out; 1894 } 1895 1896 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { 1897 err = alloc_flow_attr_counter(get_flow_counter_dev(flow), attr); 1898 if (err) 1899 goto err_out; 1900 } 1901 1902err_out: 1903 return err; 1904} 1905 1906static int 1907mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, 1908 struct mlx5e_tc_flow *flow, 1909 struct netlink_ext_ack *extack) 1910{ 1911 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1912 struct mlx5e_tc_flow_parse_attr *parse_attr; 1913 struct mlx5_flow_attr *attr = flow->attr; 1914 struct mlx5_esw_flow_attr *esw_attr; 1915 u32 max_prio, max_chain; 1916 int err = 0; 1917 1918 parse_attr = attr->parse_attr; 1919 esw_attr = attr->esw_attr; 1920 1921 /* We check chain range only for tc flows. 1922 * For ft flows, we checked attr->chain was originally 0 and set it to 1923 * FDB_FT_CHAIN which is outside tc range. 1924 * See mlx5e_rep_setup_ft_cb(). 1925 */ 1926 max_chain = mlx5_chains_get_chain_range(esw_chains(esw)); 1927 if (!mlx5e_is_ft_flow(flow) && attr->chain > max_chain) { 1928 NL_SET_ERR_MSG_MOD(extack, 1929 "Requested chain is out of supported range"); 1930 err = -EOPNOTSUPP; 1931 goto err_out; 1932 } 1933 1934 max_prio = mlx5_chains_get_prio_range(esw_chains(esw)); 1935 if (attr->prio > max_prio) { 1936 NL_SET_ERR_MSG_MOD(extack, 1937 "Requested priority is out of supported range"); 1938 err = -EOPNOTSUPP; 1939 goto err_out; 1940 } 1941 1942 if (flow_flag_test(flow, TUN_RX)) { 1943 err = mlx5e_attach_decap_route(priv, flow); 1944 if (err) 1945 goto err_out; 1946 1947 if (!attr->chain && esw_attr->int_port && 1948 attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { 1949 /* If decap route device is internal port, change the 1950 * source vport value in reg_c0 back to uplink just in 1951 * case the rule performs goto chain > 0. If we have a miss 1952 * on chain > 0 we want the metadata regs to hold the 1953 * chain id so SW will resume handling of this packet 1954 * from the proper chain. 1955 */ 1956 u32 metadata = mlx5_eswitch_get_vport_metadata_for_set(esw, 1957 esw_attr->in_rep->vport); 1958 1959 err = mlx5e_tc_match_to_reg_set(priv->mdev, &parse_attr->mod_hdr_acts, 1960 MLX5_FLOW_NAMESPACE_FDB, VPORT_TO_REG, 1961 metadata); 1962 if (err) 1963 goto err_out; 1964 1965 attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 1966 } 1967 } 1968 1969 if (flow_flag_test(flow, L3_TO_L2_DECAP)) { 1970 err = mlx5e_attach_decap(priv, flow, extack); 1971 if (err) 1972 goto err_out; 1973 } 1974 1975 if (netif_is_ovs_master(parse_attr->filter_dev)) { 1976 struct mlx5e_tc_int_port *int_port; 1977 1978 if (attr->chain) { 1979 NL_SET_ERR_MSG_MOD(extack, 1980 "Internal port rule is only supported on chain 0"); 1981 err = -EOPNOTSUPP; 1982 goto err_out; 1983 } 1984 1985 if (attr->dest_chain) { 1986 NL_SET_ERR_MSG_MOD(extack, 1987 "Internal port rule offload doesn't support goto action"); 1988 err = -EOPNOTSUPP; 1989 goto err_out; 1990 } 1991 1992 int_port = mlx5e_tc_int_port_get(mlx5e_get_int_port_priv(priv), 1993 parse_attr->filter_dev->ifindex, 1994 flow_flag_test(flow, EGRESS) ? 1995 MLX5E_TC_INT_PORT_EGRESS : 1996 MLX5E_TC_INT_PORT_INGRESS); 1997 if (IS_ERR(int_port)) { 1998 err = PTR_ERR(int_port); 1999 goto err_out; 2000 } 2001 2002 esw_attr->int_port = int_port; 2003 } 2004 2005 err = post_process_attr(flow, attr, extack); 2006 if (err) 2007 goto err_out; 2008 2009 err = mlx5e_tc_act_stats_add_flow(get_act_stats_handle(priv), flow); 2010 if (err) 2011 goto err_out; 2012 2013 /* we get here if one of the following takes place: 2014 * (1) there's no error 2015 * (2) there's an encap action and we don't have valid neigh 2016 */ 2017 if (flow_flag_test(flow, SLOW)) 2018 flow->rule[0] = mlx5e_tc_offload_to_slow_path(esw, flow, &parse_attr->spec); 2019 else 2020 flow->rule[0] = mlx5e_tc_offload_fdb_rules(esw, flow, &parse_attr->spec, attr); 2021 2022 if (IS_ERR(flow->rule[0])) { 2023 err = PTR_ERR(flow->rule[0]); 2024 goto err_out; 2025 } 2026 flow_flag_set(flow, OFFLOADED); 2027 2028 return 0; 2029 2030err_out: 2031 flow_flag_set(flow, FAILED); 2032 return err; 2033} 2034 2035static bool mlx5_flow_has_geneve_opt(struct mlx5_flow_spec *spec) 2036{ 2037 void *headers_v = MLX5_ADDR_OF(fte_match_param, 2038 spec->match_value, 2039 misc_parameters_3); 2040 u32 geneve_tlv_opt_0_data = MLX5_GET(fte_match_set_misc3, 2041 headers_v, 2042 geneve_tlv_option_0_data); 2043 2044 return !!geneve_tlv_opt_0_data; 2045} 2046 2047static void free_branch_attr(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr) 2048{ 2049 if (!attr) 2050 return; 2051 2052 mlx5_free_flow_attr_actions(flow, attr); 2053 kvfree(attr->parse_attr); 2054 kfree(attr); 2055} 2056 2057static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, 2058 struct mlx5e_tc_flow *flow) 2059{ 2060 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 2061 struct mlx5_flow_attr *attr = flow->attr; 2062 2063 mlx5e_put_flow_tunnel_id(flow); 2064 2065 remove_unready_flow(flow); 2066 2067 if (mlx5e_is_offloaded_flow(flow)) { 2068 if (flow_flag_test(flow, SLOW)) 2069 mlx5e_tc_unoffload_from_slow_path(esw, flow); 2070 else 2071 mlx5e_tc_unoffload_fdb_rules(esw, flow, attr); 2072 } 2073 complete_all(&flow->del_hw_done); 2074 2075 if (mlx5_flow_has_geneve_opt(&attr->parse_attr->spec)) 2076 mlx5_geneve_tlv_option_del(priv->mdev->geneve); 2077 2078 if (flow->decap_route) 2079 mlx5e_detach_decap_route(priv, flow); 2080 2081 mlx5_tc_ct_match_del(get_ct_priv(priv), &flow->attr->ct_attr); 2082 2083 if (flow_flag_test(flow, L3_TO_L2_DECAP)) 2084 mlx5e_detach_decap(priv, flow); 2085 2086 mlx5e_tc_act_stats_del_flow(get_act_stats_handle(priv), flow); 2087 2088 free_flow_post_acts(flow); 2089 if (flow->extra_split_attr) { 2090 mlx5_free_flow_attr_actions(flow, flow->extra_split_attr); 2091 kvfree(flow->extra_split_attr->parse_attr); 2092 kfree(flow->extra_split_attr); 2093 } 2094 mlx5_free_flow_attr_actions(flow, attr); 2095 2096 kvfree(attr->esw_attr->rx_tun_attr); 2097 kvfree(attr->parse_attr); 2098 kfree(flow->attr); 2099} 2100 2101struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow) 2102{ 2103 struct mlx5_flow_attr *attr; 2104 2105 attr = list_first_entry(&flow->attrs, struct mlx5_flow_attr, list); 2106 return attr->counter; 2107} 2108 2109/* Iterate over tmp_list of flows attached to flow_list head. */ 2110void mlx5e_put_flow_list(struct mlx5e_priv *priv, struct list_head *flow_list) 2111{ 2112 struct mlx5e_tc_flow *flow, *tmp; 2113 2114 list_for_each_entry_safe(flow, tmp, flow_list, tmp_list) 2115 mlx5e_flow_put(priv, flow); 2116} 2117 2118static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow, 2119 int peer_index) 2120{ 2121 struct mlx5_eswitch *esw = flow->priv->mdev->priv.eswitch; 2122 struct mlx5e_tc_flow *peer_flow; 2123 struct mlx5e_tc_flow *tmp; 2124 2125 if (!flow_flag_test(flow, ESWITCH) || 2126 !flow_flag_test(flow, DUP)) 2127 return; 2128 2129 mutex_lock(&esw->offloads.peer_mutex); 2130 list_del(&flow->peer[peer_index]); 2131 mutex_unlock(&esw->offloads.peer_mutex); 2132 2133 list_for_each_entry_safe(peer_flow, tmp, &flow->peer_flows, peer_flows) { 2134 if (peer_index != mlx5_get_dev_index(peer_flow->priv->mdev)) 2135 continue; 2136 2137 list_del(&peer_flow->peer_flows); 2138 if (refcount_dec_and_test(&peer_flow->refcnt)) { 2139 mlx5e_tc_del_fdb_flow(peer_flow->priv, peer_flow); 2140 kfree(peer_flow); 2141 } 2142 } 2143 2144 if (list_empty(&flow->peer_flows)) 2145 flow_flag_clear(flow, DUP); 2146} 2147 2148static void mlx5e_tc_del_fdb_peers_flow(struct mlx5e_tc_flow *flow) 2149{ 2150 struct mlx5_devcom_comp_dev *devcom; 2151 struct mlx5_devcom_comp_dev *pos; 2152 struct mlx5_eswitch *peer_esw; 2153 int i; 2154 2155 devcom = flow->priv->mdev->priv.eswitch->devcom; 2156 mlx5_devcom_for_each_peer_entry(devcom, peer_esw, pos) { 2157 i = mlx5_get_dev_index(peer_esw->dev); 2158 mlx5e_tc_del_fdb_peer_flow(flow, i); 2159 } 2160} 2161 2162static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, 2163 struct mlx5e_tc_flow *flow) 2164{ 2165 if (mlx5e_is_eswitch_flow(flow)) { 2166 struct mlx5_devcom_comp_dev *devcom = flow->priv->mdev->priv.eswitch->devcom; 2167 2168 if (!mlx5_devcom_for_each_peer_begin(devcom)) { 2169 mlx5e_tc_del_fdb_flow(priv, flow); 2170 return; 2171 } 2172 2173 mlx5e_tc_del_fdb_peers_flow(flow); 2174 mlx5_devcom_for_each_peer_end(devcom); 2175 mlx5e_tc_del_fdb_flow(priv, flow); 2176 } else { 2177 mlx5e_tc_del_nic_flow(priv, flow); 2178 } 2179} 2180 2181static bool flow_requires_tunnel_mapping(u32 chain, struct flow_cls_offload *f) 2182{ 2183 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 2184 struct flow_action *flow_action = &rule->action; 2185 const struct flow_action_entry *act; 2186 int i; 2187 2188 if (chain) 2189 return false; 2190 2191 flow_action_for_each(i, act, flow_action) { 2192 switch (act->id) { 2193 case FLOW_ACTION_GOTO: 2194 return true; 2195 case FLOW_ACTION_SAMPLE: 2196 return true; 2197 default: 2198 continue; 2199 } 2200 } 2201 2202 return false; 2203} 2204 2205static int 2206enc_opts_is_dont_care_or_full_match(struct mlx5e_priv *priv, 2207 struct flow_dissector_key_enc_opts *opts, 2208 struct netlink_ext_ack *extack, 2209 bool *dont_care) 2210{ 2211 struct geneve_opt *opt; 2212 int off = 0; 2213 2214 *dont_care = true; 2215 2216 while (opts->len > off) { 2217 opt = (struct geneve_opt *)&opts->data[off]; 2218 2219 if (!(*dont_care) || opt->opt_class || opt->type || 2220 memchr_inv(opt->opt_data, 0, opt->length * 4)) { 2221 *dont_care = false; 2222 2223 if (opt->opt_class != htons(U16_MAX) || 2224 opt->type != U8_MAX) { 2225 NL_SET_ERR_MSG_MOD(extack, 2226 "Partial match of tunnel options in chain > 0 isn't supported"); 2227 netdev_warn(priv->netdev, 2228 "Partial match of tunnel options in chain > 0 isn't supported"); 2229 return -EOPNOTSUPP; 2230 } 2231 } 2232 2233 off += sizeof(struct geneve_opt) + opt->length * 4; 2234 } 2235 2236 return 0; 2237} 2238 2239#define COPY_DISSECTOR(rule, diss_key, dst)\ 2240({ \ 2241 struct flow_rule *__rule = (rule);\ 2242 typeof(dst) __dst = dst;\ 2243\ 2244 memcpy(__dst,\ 2245 skb_flow_dissector_target(__rule->match.dissector,\ 2246 diss_key,\ 2247 __rule->match.key),\ 2248 sizeof(*__dst));\ 2249}) 2250 2251static int mlx5e_get_flow_tunnel_id(struct mlx5e_priv *priv, 2252 struct mlx5e_tc_flow *flow, 2253 struct flow_cls_offload *f, 2254 struct net_device *filter_dev) 2255{ 2256 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 2257 struct netlink_ext_ack *extack = f->common.extack; 2258 struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts; 2259 struct flow_match_enc_opts enc_opts_match; 2260 struct tunnel_match_enc_opts tun_enc_opts; 2261 struct mlx5_rep_uplink_priv *uplink_priv; 2262 struct mlx5_flow_attr *attr = flow->attr; 2263 struct mlx5e_rep_priv *uplink_rpriv; 2264 struct tunnel_match_key tunnel_key; 2265 bool enc_opts_is_dont_care = true; 2266 u32 tun_id, enc_opts_id = 0; 2267 struct mlx5_eswitch *esw; 2268 u32 value, mask; 2269 int err; 2270 2271 esw = priv->mdev->priv.eswitch; 2272 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 2273 uplink_priv = &uplink_rpriv->uplink_priv; 2274 2275 memset(&tunnel_key, 0, sizeof(tunnel_key)); 2276 COPY_DISSECTOR(rule, FLOW_DISSECTOR_KEY_ENC_CONTROL, 2277 &tunnel_key.enc_control); 2278 if (tunnel_key.enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) 2279 COPY_DISSECTOR(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, 2280 &tunnel_key.enc_ipv4); 2281 else 2282 COPY_DISSECTOR(rule, FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, 2283 &tunnel_key.enc_ipv6); 2284 COPY_DISSECTOR(rule, FLOW_DISSECTOR_KEY_ENC_IP, &tunnel_key.enc_ip); 2285 COPY_DISSECTOR(rule, FLOW_DISSECTOR_KEY_ENC_PORTS, 2286 &tunnel_key.enc_tp); 2287 COPY_DISSECTOR(rule, FLOW_DISSECTOR_KEY_ENC_KEYID, 2288 &tunnel_key.enc_key_id); 2289 tunnel_key.filter_ifindex = filter_dev->ifindex; 2290 2291 err = mapping_add(uplink_priv->tunnel_mapping, &tunnel_key, &tun_id); 2292 if (err) 2293 return err; 2294 2295 flow_rule_match_enc_opts(rule, &enc_opts_match); 2296 err = enc_opts_is_dont_care_or_full_match(priv, 2297 enc_opts_match.mask, 2298 extack, 2299 &enc_opts_is_dont_care); 2300 if (err) 2301 goto err_enc_opts; 2302 2303 if (!enc_opts_is_dont_care) { 2304 memset(&tun_enc_opts, 0, sizeof(tun_enc_opts)); 2305 memcpy(&tun_enc_opts.key, enc_opts_match.key, 2306 sizeof(*enc_opts_match.key)); 2307 memcpy(&tun_enc_opts.mask, enc_opts_match.mask, 2308 sizeof(*enc_opts_match.mask)); 2309 2310 err = mapping_add(uplink_priv->tunnel_enc_opts_mapping, 2311 &tun_enc_opts, &enc_opts_id); 2312 if (err) 2313 goto err_enc_opts; 2314 } 2315 2316 value = tun_id << ENC_OPTS_BITS | enc_opts_id; 2317 mask = enc_opts_id ? TUNNEL_ID_MASK : 2318 (TUNNEL_ID_MASK & ~ENC_OPTS_BITS_MASK); 2319 2320 if (attr->chain) { 2321 mlx5e_tc_match_to_reg_match(&attr->parse_attr->spec, 2322 TUNNEL_TO_REG, value, mask); 2323 } else { 2324 mod_hdr_acts = &attr->parse_attr->mod_hdr_acts; 2325 err = mlx5e_tc_match_to_reg_set(priv->mdev, 2326 mod_hdr_acts, MLX5_FLOW_NAMESPACE_FDB, 2327 TUNNEL_TO_REG, value); 2328 if (err) 2329 goto err_set; 2330 2331 attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 2332 } 2333 2334 flow->attr->tunnel_id = value; 2335 return 0; 2336 2337err_set: 2338 if (enc_opts_id) 2339 mapping_remove(uplink_priv->tunnel_enc_opts_mapping, 2340 enc_opts_id); 2341err_enc_opts: 2342 mapping_remove(uplink_priv->tunnel_mapping, tun_id); 2343 return err; 2344} 2345 2346static void mlx5e_put_flow_tunnel_id(struct mlx5e_tc_flow *flow) 2347{ 2348 u32 enc_opts_id = flow->attr->tunnel_id & ENC_OPTS_BITS_MASK; 2349 u32 tun_id = flow->attr->tunnel_id >> ENC_OPTS_BITS; 2350 struct mlx5_rep_uplink_priv *uplink_priv; 2351 struct mlx5e_rep_priv *uplink_rpriv; 2352 struct mlx5_eswitch *esw; 2353 2354 esw = flow->priv->mdev->priv.eswitch; 2355 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 2356 uplink_priv = &uplink_rpriv->uplink_priv; 2357 2358 if (tun_id) 2359 mapping_remove(uplink_priv->tunnel_mapping, tun_id); 2360 if (enc_opts_id) 2361 mapping_remove(uplink_priv->tunnel_enc_opts_mapping, 2362 enc_opts_id); 2363} 2364 2365void mlx5e_tc_set_ethertype(struct mlx5_core_dev *mdev, 2366 struct flow_match_basic *match, bool outer, 2367 void *headers_c, void *headers_v) 2368{ 2369 bool ip_version_cap; 2370 2371 ip_version_cap = outer ? 2372 MLX5_CAP_FLOWTABLE_NIC_RX(mdev, 2373 ft_field_support.outer_ip_version) : 2374 MLX5_CAP_FLOWTABLE_NIC_RX(mdev, 2375 ft_field_support.inner_ip_version); 2376 2377 if (ip_version_cap && match->mask->n_proto == htons(0xFFFF) && 2378 (match->key->n_proto == htons(ETH_P_IP) || 2379 match->key->n_proto == htons(ETH_P_IPV6))) { 2380 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_version); 2381 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version, 2382 match->key->n_proto == htons(ETH_P_IP) ? 4 : 6); 2383 } else { 2384 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype, 2385 ntohs(match->mask->n_proto)); 2386 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, 2387 ntohs(match->key->n_proto)); 2388 } 2389} 2390 2391u8 mlx5e_tc_get_ip_version(struct mlx5_flow_spec *spec, bool outer) 2392{ 2393 void *headers_v; 2394 u16 ethertype; 2395 u8 ip_version; 2396 2397 if (outer) 2398 headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers); 2399 else 2400 headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, inner_headers); 2401 2402 ip_version = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ip_version); 2403 /* Return ip_version converted from ethertype anyway */ 2404 if (!ip_version) { 2405 ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype); 2406 if (ethertype == ETH_P_IP || ethertype == ETH_P_ARP) 2407 ip_version = 4; 2408 else if (ethertype == ETH_P_IPV6) 2409 ip_version = 6; 2410 } 2411 return ip_version; 2412} 2413 2414/* Tunnel device follows RFC 6040, see include/net/inet_ecn.h. 2415 * And changes inner ip_ecn depending on inner and outer ip_ecn as follows: 2416 * +---------+----------------------------------------+ 2417 * |Arriving | Arriving Outer Header | 2418 * | Inner +---------+---------+---------+----------+ 2419 * | Header | Not-ECT | ECT(0) | ECT(1) | CE | 2420 * +---------+---------+---------+---------+----------+ 2421 * | Not-ECT | Not-ECT | Not-ECT | Not-ECT | <drop> | 2422 * | ECT(0) | ECT(0) | ECT(0) | ECT(1) | CE* | 2423 * | ECT(1) | ECT(1) | ECT(1) | ECT(1)* | CE* | 2424 * | CE | CE | CE | CE | CE | 2425 * +---------+---------+---------+---------+----------+ 2426 * 2427 * Tc matches on inner after decapsulation on tunnel device, but hw offload matches 2428 * the inner ip_ecn value before hardware decap action. 2429 * 2430 * Cells marked are changed from original inner packet ip_ecn value during decap, and 2431 * so matching those values on inner ip_ecn before decap will fail. 2432 * 2433 * The following helper allows offload when inner ip_ecn won't be changed by outer ip_ecn, 2434 * except for the outer ip_ecn = CE, where in all cases inner ip_ecn will be changed to CE, 2435 * and such we can drop the inner ip_ecn=CE match. 2436 */ 2437 2438static int mlx5e_tc_verify_tunnel_ecn(struct mlx5e_priv *priv, 2439 struct flow_cls_offload *f, 2440 bool *match_inner_ecn) 2441{ 2442 u8 outer_ecn_mask = 0, outer_ecn_key = 0, inner_ecn_mask = 0, inner_ecn_key = 0; 2443 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 2444 struct netlink_ext_ack *extack = f->common.extack; 2445 struct flow_match_ip match; 2446 2447 *match_inner_ecn = true; 2448 2449 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) { 2450 flow_rule_match_enc_ip(rule, &match); 2451 outer_ecn_key = match.key->tos & INET_ECN_MASK; 2452 outer_ecn_mask = match.mask->tos & INET_ECN_MASK; 2453 } 2454 2455 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) { 2456 flow_rule_match_ip(rule, &match); 2457 inner_ecn_key = match.key->tos & INET_ECN_MASK; 2458 inner_ecn_mask = match.mask->tos & INET_ECN_MASK; 2459 } 2460 2461 if (outer_ecn_mask != 0 && outer_ecn_mask != INET_ECN_MASK) { 2462 NL_SET_ERR_MSG_MOD(extack, "Partial match on enc_tos ecn bits isn't supported"); 2463 netdev_warn(priv->netdev, "Partial match on enc_tos ecn bits isn't supported"); 2464 return -EOPNOTSUPP; 2465 } 2466 2467 if (!outer_ecn_mask) { 2468 if (!inner_ecn_mask) 2469 return 0; 2470 2471 NL_SET_ERR_MSG_MOD(extack, 2472 "Matching on tos ecn bits without also matching enc_tos ecn bits isn't supported"); 2473 netdev_warn(priv->netdev, 2474 "Matching on tos ecn bits without also matching enc_tos ecn bits isn't supported"); 2475 return -EOPNOTSUPP; 2476 } 2477 2478 if (inner_ecn_mask && inner_ecn_mask != INET_ECN_MASK) { 2479 NL_SET_ERR_MSG_MOD(extack, 2480 "Partial match on tos ecn bits with match on enc_tos ecn bits isn't supported"); 2481 netdev_warn(priv->netdev, 2482 "Partial match on tos ecn bits with match on enc_tos ecn bits isn't supported"); 2483 return -EOPNOTSUPP; 2484 } 2485 2486 if (!inner_ecn_mask) 2487 return 0; 2488 2489 /* Both inner and outer have full mask on ecn */ 2490 2491 if (outer_ecn_key == INET_ECN_ECT_1) { 2492 /* inner ecn might change by DECAP action */ 2493 2494 NL_SET_ERR_MSG_MOD(extack, "Match on enc_tos ecn = ECT(1) isn't supported"); 2495 netdev_warn(priv->netdev, "Match on enc_tos ecn = ECT(1) isn't supported"); 2496 return -EOPNOTSUPP; 2497 } 2498 2499 if (outer_ecn_key != INET_ECN_CE) 2500 return 0; 2501 2502 if (inner_ecn_key != INET_ECN_CE) { 2503 /* Can't happen in software, as packet ecn will be changed to CE after decap */ 2504 NL_SET_ERR_MSG_MOD(extack, 2505 "Match on tos enc_tos ecn = CE while match on tos ecn != CE isn't supported"); 2506 netdev_warn(priv->netdev, 2507 "Match on tos enc_tos ecn = CE while match on tos ecn != CE isn't supported"); 2508 return -EOPNOTSUPP; 2509 } 2510 2511 /* outer ecn = CE, inner ecn = CE, as decap will change inner ecn to CE in anycase, 2512 * drop match on inner ecn 2513 */ 2514 *match_inner_ecn = false; 2515 2516 return 0; 2517} 2518 2519static int parse_tunnel_attr(struct mlx5e_priv *priv, 2520 struct mlx5e_tc_flow *flow, 2521 struct mlx5_flow_spec *spec, 2522 struct flow_cls_offload *f, 2523 struct net_device *filter_dev, 2524 u8 *match_level, 2525 bool *match_inner) 2526{ 2527 struct mlx5e_tc_tunnel *tunnel = mlx5e_get_tc_tun(filter_dev); 2528 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 2529 struct netlink_ext_ack *extack = f->common.extack; 2530 bool needs_mapping, sets_mapping; 2531 int err; 2532 2533 if (!mlx5e_is_eswitch_flow(flow)) { 2534 NL_SET_ERR_MSG_MOD(extack, "Match on tunnel is not supported"); 2535 return -EOPNOTSUPP; 2536 } 2537 2538 needs_mapping = !!flow->attr->chain; 2539 sets_mapping = flow_requires_tunnel_mapping(flow->attr->chain, f); 2540 *match_inner = !needs_mapping; 2541 2542 if ((needs_mapping || sets_mapping) && 2543 !mlx5_eswitch_reg_c1_loopback_enabled(esw)) { 2544 NL_SET_ERR_MSG_MOD(extack, 2545 "Chains on tunnel devices isn't supported without register loopback support"); 2546 netdev_warn(priv->netdev, 2547 "Chains on tunnel devices isn't supported without register loopback support"); 2548 return -EOPNOTSUPP; 2549 } 2550 2551 if (!flow->attr->chain) { 2552 err = mlx5e_tc_tun_parse(filter_dev, priv, spec, f, 2553 match_level); 2554 if (err) { 2555 NL_SET_ERR_MSG_MOD(extack, 2556 "Failed to parse tunnel attributes"); 2557 netdev_warn(priv->netdev, 2558 "Failed to parse tunnel attributes"); 2559 return err; 2560 } 2561 2562 /* With mpls over udp we decapsulate using packet reformat 2563 * object 2564 */ 2565 if (!netif_is_bareudp(filter_dev)) 2566 flow->attr->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP; 2567 err = mlx5e_tc_set_attr_rx_tun(flow, spec); 2568 if (err) 2569 return err; 2570 } else if (tunnel) { 2571 struct mlx5_flow_spec *tmp_spec; 2572 2573 tmp_spec = kvzalloc(sizeof(*tmp_spec), GFP_KERNEL); 2574 if (!tmp_spec) { 2575 NL_SET_ERR_MSG_MOD(extack, "Failed to allocate memory for tunnel tmp spec"); 2576 netdev_warn(priv->netdev, "Failed to allocate memory for tunnel tmp spec"); 2577 return -ENOMEM; 2578 } 2579 memcpy(tmp_spec, spec, sizeof(*tmp_spec)); 2580 2581 err = mlx5e_tc_tun_parse(filter_dev, priv, tmp_spec, f, match_level); 2582 if (err) { 2583 NL_SET_ERR_MSG_MOD(extack, "Failed to parse tunnel attributes"); 2584 netdev_warn(priv->netdev, "Failed to parse tunnel attributes"); 2585 } else { 2586 err = mlx5e_tc_set_attr_rx_tun(flow, tmp_spec); 2587 } 2588 if (mlx5_flow_has_geneve_opt(tmp_spec)) 2589 mlx5_geneve_tlv_option_del(priv->mdev->geneve); 2590 kvfree(tmp_spec); 2591 if (err) 2592 return err; 2593 } 2594 2595 if (!needs_mapping && !sets_mapping) 2596 return 0; 2597 2598 return mlx5e_get_flow_tunnel_id(priv, flow, f, filter_dev); 2599} 2600 2601static void *get_match_inner_headers_criteria(struct mlx5_flow_spec *spec) 2602{ 2603 return MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 2604 inner_headers); 2605} 2606 2607static void *get_match_inner_headers_value(struct mlx5_flow_spec *spec) 2608{ 2609 return MLX5_ADDR_OF(fte_match_param, spec->match_value, 2610 inner_headers); 2611} 2612 2613static void *get_match_outer_headers_criteria(struct mlx5_flow_spec *spec) 2614{ 2615 return MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 2616 outer_headers); 2617} 2618 2619static void *get_match_outer_headers_value(struct mlx5_flow_spec *spec) 2620{ 2621 return MLX5_ADDR_OF(fte_match_param, spec->match_value, 2622 outer_headers); 2623} 2624 2625void *mlx5e_get_match_headers_value(u32 flags, struct mlx5_flow_spec *spec) 2626{ 2627 return (flags & MLX5_FLOW_CONTEXT_ACTION_DECAP) ? 2628 get_match_inner_headers_value(spec) : 2629 get_match_outer_headers_value(spec); 2630} 2631 2632void *mlx5e_get_match_headers_criteria(u32 flags, struct mlx5_flow_spec *spec) 2633{ 2634 return (flags & MLX5_FLOW_CONTEXT_ACTION_DECAP) ? 2635 get_match_inner_headers_criteria(spec) : 2636 get_match_outer_headers_criteria(spec); 2637} 2638 2639static int mlx5e_flower_parse_meta(struct net_device *filter_dev, 2640 struct flow_cls_offload *f) 2641{ 2642 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 2643 struct netlink_ext_ack *extack = f->common.extack; 2644 struct net_device *ingress_dev; 2645 struct flow_match_meta match; 2646 2647 if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) 2648 return 0; 2649 2650 flow_rule_match_meta(rule, &match); 2651 2652 if (match.mask->l2_miss) { 2653 NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on \"l2_miss\""); 2654 return -EOPNOTSUPP; 2655 } 2656 2657 if (!match.mask->ingress_ifindex) 2658 return 0; 2659 2660 if (match.mask->ingress_ifindex != 0xFFFFFFFF) { 2661 NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask"); 2662 return -EOPNOTSUPP; 2663 } 2664 2665 ingress_dev = __dev_get_by_index(dev_net(filter_dev), 2666 match.key->ingress_ifindex); 2667 if (!ingress_dev) { 2668 NL_SET_ERR_MSG_MOD(extack, 2669 "Can't find the ingress port to match on"); 2670 return -ENOENT; 2671 } 2672 2673 if (ingress_dev != filter_dev) { 2674 NL_SET_ERR_MSG_MOD(extack, 2675 "Can't match on the ingress filter port"); 2676 return -EOPNOTSUPP; 2677 } 2678 2679 return 0; 2680} 2681 2682static bool skip_key_basic(struct net_device *filter_dev, 2683 struct flow_cls_offload *f) 2684{ 2685 /* When doing mpls over udp decap, the user needs to provide 2686 * MPLS_UC as the protocol in order to be able to match on mpls 2687 * label fields. However, the actual ethertype is IP so we want to 2688 * avoid matching on this, otherwise we'll fail the match. 2689 */ 2690 if (netif_is_bareudp(filter_dev) && f->common.chain_index == 0) 2691 return true; 2692 2693 return false; 2694} 2695 2696static int __parse_cls_flower(struct mlx5e_priv *priv, 2697 struct mlx5e_tc_flow *flow, 2698 struct mlx5_flow_spec *spec, 2699 struct flow_cls_offload *f, 2700 struct net_device *filter_dev, 2701 u8 *inner_match_level, u8 *outer_match_level) 2702{ 2703 struct netlink_ext_ack *extack = f->common.extack; 2704 void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 2705 outer_headers); 2706 void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, 2707 outer_headers); 2708 void *misc_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 2709 misc_parameters); 2710 void *misc_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, 2711 misc_parameters); 2712 void *misc_c_3 = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 2713 misc_parameters_3); 2714 void *misc_v_3 = MLX5_ADDR_OF(fte_match_param, spec->match_value, 2715 misc_parameters_3); 2716 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 2717 struct flow_dissector *dissector = rule->match.dissector; 2718 enum fs_flow_table_type fs_type; 2719 bool match_inner_ecn = true; 2720 u16 addr_type = 0; 2721 u8 ip_proto = 0; 2722 u8 *match_level; 2723 int err; 2724 2725 fs_type = mlx5e_is_eswitch_flow(flow) ? FS_FT_FDB : FS_FT_NIC_RX; 2726 match_level = outer_match_level; 2727 2728 if (dissector->used_keys & 2729 ~(BIT_ULL(FLOW_DISSECTOR_KEY_META) | 2730 BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | 2731 BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | 2732 BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 2733 BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | 2734 BIT_ULL(FLOW_DISSECTOR_KEY_CVLAN) | 2735 BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | 2736 BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | 2737 BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | 2738 BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID) | 2739 BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | 2740 BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | 2741 BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS) | 2742 BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL) | 2743 BIT_ULL(FLOW_DISSECTOR_KEY_TCP) | 2744 BIT_ULL(FLOW_DISSECTOR_KEY_IP) | 2745 BIT_ULL(FLOW_DISSECTOR_KEY_CT) | 2746 BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP) | 2747 BIT_ULL(FLOW_DISSECTOR_KEY_ENC_OPTS) | 2748 BIT_ULL(FLOW_DISSECTOR_KEY_ICMP) | 2749 BIT_ULL(FLOW_DISSECTOR_KEY_MPLS))) { 2750 NL_SET_ERR_MSG_MOD(extack, "Unsupported key"); 2751 netdev_dbg(priv->netdev, "Unsupported key used: 0x%llx\n", 2752 dissector->used_keys); 2753 return -EOPNOTSUPP; 2754 } 2755 2756 if (mlx5e_get_tc_tun(filter_dev)) { 2757 bool match_inner = false; 2758 2759 err = parse_tunnel_attr(priv, flow, spec, f, filter_dev, 2760 outer_match_level, &match_inner); 2761 if (err) 2762 return err; 2763 2764 if (match_inner) { 2765 /* header pointers should point to the inner headers 2766 * if the packet was decapsulated already. 2767 * outer headers are set by parse_tunnel_attr. 2768 */ 2769 match_level = inner_match_level; 2770 headers_c = get_match_inner_headers_criteria(spec); 2771 headers_v = get_match_inner_headers_value(spec); 2772 } 2773 2774 err = mlx5e_tc_verify_tunnel_ecn(priv, f, &match_inner_ecn); 2775 if (err) 2776 return err; 2777 } 2778 2779 err = mlx5e_flower_parse_meta(filter_dev, f); 2780 if (err) 2781 return err; 2782 2783 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC) && 2784 !skip_key_basic(filter_dev, f)) { 2785 struct flow_match_basic match; 2786 2787 flow_rule_match_basic(rule, &match); 2788 mlx5e_tc_set_ethertype(priv->mdev, &match, 2789 match_level == outer_match_level, 2790 headers_c, headers_v); 2791 2792 if (match.mask->n_proto) 2793 *match_level = MLX5_MATCH_L2; 2794 } 2795 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN) || 2796 is_vlan_dev(filter_dev)) { 2797 struct flow_dissector_key_vlan filter_dev_mask; 2798 struct flow_dissector_key_vlan filter_dev_key; 2799 struct flow_match_vlan match; 2800 2801 if (is_vlan_dev(filter_dev)) { 2802 match.key = &filter_dev_key; 2803 match.key->vlan_id = vlan_dev_vlan_id(filter_dev); 2804 match.key->vlan_tpid = vlan_dev_vlan_proto(filter_dev); 2805 match.key->vlan_priority = 0; 2806 match.mask = &filter_dev_mask; 2807 memset(match.mask, 0xff, sizeof(*match.mask)); 2808 match.mask->vlan_priority = 0; 2809 } else { 2810 flow_rule_match_vlan(rule, &match); 2811 } 2812 if (match.mask->vlan_id || 2813 match.mask->vlan_priority || 2814 match.mask->vlan_tpid) { 2815 if (match.key->vlan_tpid == htons(ETH_P_8021AD)) { 2816 MLX5_SET(fte_match_set_lyr_2_4, headers_c, 2817 svlan_tag, 1); 2818 MLX5_SET(fte_match_set_lyr_2_4, headers_v, 2819 svlan_tag, 1); 2820 } else { 2821 MLX5_SET(fte_match_set_lyr_2_4, headers_c, 2822 cvlan_tag, 1); 2823 MLX5_SET(fte_match_set_lyr_2_4, headers_v, 2824 cvlan_tag, 1); 2825 } 2826 2827 MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_vid, 2828 match.mask->vlan_id); 2829 MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid, 2830 match.key->vlan_id); 2831 2832 MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_prio, 2833 match.mask->vlan_priority); 2834 MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio, 2835 match.key->vlan_priority); 2836 2837 *match_level = MLX5_MATCH_L2; 2838 2839 if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN) && 2840 match.mask->vlan_eth_type && 2841 MLX5_CAP_FLOWTABLE_TYPE(priv->mdev, 2842 ft_field_support.outer_second_vid, 2843 fs_type)) { 2844 MLX5_SET(fte_match_set_misc, misc_c, 2845 outer_second_cvlan_tag, 1); 2846 spec->match_criteria_enable |= 2847 MLX5_MATCH_MISC_PARAMETERS; 2848 } 2849 } 2850 } else if (*match_level != MLX5_MATCH_NONE) { 2851 /* cvlan_tag enabled in match criteria and 2852 * disabled in match value means both S & C tags 2853 * don't exist (untagged of both) 2854 */ 2855 MLX5_SET(fte_match_set_lyr_2_4, headers_c, cvlan_tag, 1); 2856 *match_level = MLX5_MATCH_L2; 2857 } 2858 2859 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) { 2860 struct flow_match_vlan match; 2861 2862 flow_rule_match_cvlan(rule, &match); 2863 if (match.mask->vlan_id || 2864 match.mask->vlan_priority || 2865 match.mask->vlan_tpid) { 2866 if (!MLX5_CAP_FLOWTABLE_TYPE(priv->mdev, ft_field_support.outer_second_vid, 2867 fs_type)) { 2868 NL_SET_ERR_MSG_MOD(extack, 2869 "Matching on CVLAN is not supported"); 2870 return -EOPNOTSUPP; 2871 } 2872 2873 if (match.key->vlan_tpid == htons(ETH_P_8021AD)) { 2874 MLX5_SET(fte_match_set_misc, misc_c, 2875 outer_second_svlan_tag, 1); 2876 MLX5_SET(fte_match_set_misc, misc_v, 2877 outer_second_svlan_tag, 1); 2878 } else { 2879 MLX5_SET(fte_match_set_misc, misc_c, 2880 outer_second_cvlan_tag, 1); 2881 MLX5_SET(fte_match_set_misc, misc_v, 2882 outer_second_cvlan_tag, 1); 2883 } 2884 2885 MLX5_SET(fte_match_set_misc, misc_c, outer_second_vid, 2886 match.mask->vlan_id); 2887 MLX5_SET(fte_match_set_misc, misc_v, outer_second_vid, 2888 match.key->vlan_id); 2889 MLX5_SET(fte_match_set_misc, misc_c, outer_second_prio, 2890 match.mask->vlan_priority); 2891 MLX5_SET(fte_match_set_misc, misc_v, outer_second_prio, 2892 match.key->vlan_priority); 2893 2894 *match_level = MLX5_MATCH_L2; 2895 spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS; 2896 } 2897 } 2898 2899 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { 2900 struct flow_match_eth_addrs match; 2901 2902 flow_rule_match_eth_addrs(rule, &match); 2903 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, 2904 dmac_47_16), 2905 match.mask->dst); 2906 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, 2907 dmac_47_16), 2908 match.key->dst); 2909 2910 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, 2911 smac_47_16), 2912 match.mask->src); 2913 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, 2914 smac_47_16), 2915 match.key->src); 2916 2917 if (!is_zero_ether_addr(match.mask->src) || 2918 !is_zero_ether_addr(match.mask->dst)) 2919 *match_level = MLX5_MATCH_L2; 2920 } 2921 2922 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { 2923 struct flow_match_control match; 2924 2925 flow_rule_match_control(rule, &match); 2926 addr_type = match.key->addr_type; 2927 2928 if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) { 2929 MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1); 2930 MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 2931 match.key->flags & FLOW_DIS_IS_FRAGMENT); 2932 2933 /* the HW doesn't need L3 inline to match on frag=no */ 2934 if (!(match.key->flags & FLOW_DIS_IS_FRAGMENT)) 2935 *match_level = MLX5_MATCH_L2; 2936 /* *** L2 attributes parsing up to here *** */ 2937 else 2938 *match_level = MLX5_MATCH_L3; 2939 } 2940 2941 if (!flow_rule_is_supp_control_flags(FLOW_DIS_IS_FRAGMENT, 2942 match.mask->flags, extack)) 2943 return -EOPNOTSUPP; 2944 } 2945 2946 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { 2947 struct flow_match_basic match; 2948 2949 flow_rule_match_basic(rule, &match); 2950 ip_proto = match.key->ip_proto; 2951 2952 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol, 2953 match.mask->ip_proto); 2954 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 2955 match.key->ip_proto); 2956 2957 if (match.mask->ip_proto) 2958 *match_level = MLX5_MATCH_L3; 2959 } 2960 2961 if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { 2962 struct flow_match_ipv4_addrs match; 2963 2964 flow_rule_match_ipv4_addrs(rule, &match); 2965 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, 2966 src_ipv4_src_ipv6.ipv4_layout.ipv4), 2967 &match.mask->src, sizeof(match.mask->src)); 2968 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, 2969 src_ipv4_src_ipv6.ipv4_layout.ipv4), 2970 &match.key->src, sizeof(match.key->src)); 2971 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, 2972 dst_ipv4_dst_ipv6.ipv4_layout.ipv4), 2973 &match.mask->dst, sizeof(match.mask->dst)); 2974 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, 2975 dst_ipv4_dst_ipv6.ipv4_layout.ipv4), 2976 &match.key->dst, sizeof(match.key->dst)); 2977 2978 if (match.mask->src || match.mask->dst) 2979 *match_level = MLX5_MATCH_L3; 2980 } 2981 2982 if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { 2983 struct flow_match_ipv6_addrs match; 2984 2985 flow_rule_match_ipv6_addrs(rule, &match); 2986 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, 2987 src_ipv4_src_ipv6.ipv6_layout.ipv6), 2988 &match.mask->src, sizeof(match.mask->src)); 2989 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, 2990 src_ipv4_src_ipv6.ipv6_layout.ipv6), 2991 &match.key->src, sizeof(match.key->src)); 2992 2993 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, 2994 dst_ipv4_dst_ipv6.ipv6_layout.ipv6), 2995 &match.mask->dst, sizeof(match.mask->dst)); 2996 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, 2997 dst_ipv4_dst_ipv6.ipv6_layout.ipv6), 2998 &match.key->dst, sizeof(match.key->dst)); 2999 3000 if (ipv6_addr_type(&match.mask->src) != IPV6_ADDR_ANY || 3001 ipv6_addr_type(&match.mask->dst) != IPV6_ADDR_ANY) 3002 *match_level = MLX5_MATCH_L3; 3003 } 3004 3005 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) { 3006 struct flow_match_ip match; 3007 3008 flow_rule_match_ip(rule, &match); 3009 if (match_inner_ecn) { 3010 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn, 3011 match.mask->tos & 0x3); 3012 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, 3013 match.key->tos & 0x3); 3014 } 3015 3016 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp, 3017 match.mask->tos >> 2); 3018 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, 3019 match.key->tos >> 2); 3020 3021 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit, 3022 match.mask->ttl); 3023 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit, 3024 match.key->ttl); 3025 3026 if (match.mask->ttl && 3027 !MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev, 3028 ft_field_support.outer_ipv4_ttl)) { 3029 NL_SET_ERR_MSG_MOD(extack, 3030 "Matching on TTL is not supported"); 3031 return -EOPNOTSUPP; 3032 } 3033 3034 if (match.mask->tos || match.mask->ttl) 3035 *match_level = MLX5_MATCH_L3; 3036 } 3037 3038 /* *** L3 attributes parsing up to here *** */ 3039 3040 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { 3041 struct flow_match_ports match; 3042 3043 flow_rule_match_ports(rule, &match); 3044 switch (ip_proto) { 3045 case IPPROTO_TCP: 3046 MLX5_SET(fte_match_set_lyr_2_4, headers_c, 3047 tcp_sport, ntohs(match.mask->src)); 3048 MLX5_SET(fte_match_set_lyr_2_4, headers_v, 3049 tcp_sport, ntohs(match.key->src)); 3050 3051 MLX5_SET(fte_match_set_lyr_2_4, headers_c, 3052 tcp_dport, ntohs(match.mask->dst)); 3053 MLX5_SET(fte_match_set_lyr_2_4, headers_v, 3054 tcp_dport, ntohs(match.key->dst)); 3055 break; 3056 3057 case IPPROTO_UDP: 3058 MLX5_SET(fte_match_set_lyr_2_4, headers_c, 3059 udp_sport, ntohs(match.mask->src)); 3060 MLX5_SET(fte_match_set_lyr_2_4, headers_v, 3061 udp_sport, ntohs(match.key->src)); 3062 3063 MLX5_SET(fte_match_set_lyr_2_4, headers_c, 3064 udp_dport, ntohs(match.mask->dst)); 3065 MLX5_SET(fte_match_set_lyr_2_4, headers_v, 3066 udp_dport, ntohs(match.key->dst)); 3067 break; 3068 default: 3069 NL_SET_ERR_MSG_MOD(extack, 3070 "Only UDP and TCP transports are supported for L4 matching"); 3071 netdev_err(priv->netdev, 3072 "Only UDP and TCP transport are supported\n"); 3073 return -EINVAL; 3074 } 3075 3076 if (match.mask->src || match.mask->dst) 3077 *match_level = MLX5_MATCH_L4; 3078 } 3079 3080 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) { 3081 struct flow_match_tcp match; 3082 3083 flow_rule_match_tcp(rule, &match); 3084 MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_flags, 3085 ntohs(match.mask->flags)); 3086 MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_flags, 3087 ntohs(match.key->flags)); 3088 3089 if (match.mask->flags) 3090 *match_level = MLX5_MATCH_L4; 3091 } 3092 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ICMP)) { 3093 struct flow_match_icmp match; 3094 3095 flow_rule_match_icmp(rule, &match); 3096 switch (ip_proto) { 3097 case IPPROTO_ICMP: 3098 if (!(MLX5_CAP_GEN(priv->mdev, flex_parser_protocols) & 3099 MLX5_FLEX_PROTO_ICMP)) { 3100 NL_SET_ERR_MSG_MOD(extack, 3101 "Match on Flex protocols for ICMP is not supported"); 3102 return -EOPNOTSUPP; 3103 } 3104 MLX5_SET(fte_match_set_misc3, misc_c_3, icmp_type, 3105 match.mask->type); 3106 MLX5_SET(fte_match_set_misc3, misc_v_3, icmp_type, 3107 match.key->type); 3108 MLX5_SET(fte_match_set_misc3, misc_c_3, icmp_code, 3109 match.mask->code); 3110 MLX5_SET(fte_match_set_misc3, misc_v_3, icmp_code, 3111 match.key->code); 3112 break; 3113 case IPPROTO_ICMPV6: 3114 if (!(MLX5_CAP_GEN(priv->mdev, flex_parser_protocols) & 3115 MLX5_FLEX_PROTO_ICMPV6)) { 3116 NL_SET_ERR_MSG_MOD(extack, 3117 "Match on Flex protocols for ICMPV6 is not supported"); 3118 return -EOPNOTSUPP; 3119 } 3120 MLX5_SET(fte_match_set_misc3, misc_c_3, icmpv6_type, 3121 match.mask->type); 3122 MLX5_SET(fte_match_set_misc3, misc_v_3, icmpv6_type, 3123 match.key->type); 3124 MLX5_SET(fte_match_set_misc3, misc_c_3, icmpv6_code, 3125 match.mask->code); 3126 MLX5_SET(fte_match_set_misc3, misc_v_3, icmpv6_code, 3127 match.key->code); 3128 break; 3129 default: 3130 NL_SET_ERR_MSG_MOD(extack, 3131 "Code and type matching only with ICMP and ICMPv6"); 3132 netdev_err(priv->netdev, 3133 "Code and type matching only with ICMP and ICMPv6\n"); 3134 return -EINVAL; 3135 } 3136 if (match.mask->code || match.mask->type) { 3137 *match_level = MLX5_MATCH_L4; 3138 spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_3; 3139 } 3140 } 3141 /* Currently supported only for MPLS over UDP */ 3142 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS) && 3143 !netif_is_bareudp(filter_dev)) { 3144 NL_SET_ERR_MSG_MOD(extack, 3145 "Matching on MPLS is supported only for MPLS over UDP"); 3146 netdev_err(priv->netdev, 3147 "Matching on MPLS is supported only for MPLS over UDP\n"); 3148 return -EOPNOTSUPP; 3149 } 3150 3151 return 0; 3152} 3153 3154static int parse_cls_flower(struct mlx5e_priv *priv, 3155 struct mlx5e_tc_flow *flow, 3156 struct mlx5_flow_spec *spec, 3157 struct flow_cls_offload *f, 3158 struct net_device *filter_dev) 3159{ 3160 u8 inner_match_level, outer_match_level, non_tunnel_match_level; 3161 struct netlink_ext_ack *extack = f->common.extack; 3162 struct mlx5_core_dev *dev = priv->mdev; 3163 struct mlx5_eswitch *esw = dev->priv.eswitch; 3164 struct mlx5e_rep_priv *rpriv = priv->ppriv; 3165 struct mlx5_eswitch_rep *rep; 3166 bool is_eswitch_flow; 3167 int err; 3168 3169 inner_match_level = MLX5_MATCH_NONE; 3170 outer_match_level = MLX5_MATCH_NONE; 3171 3172 err = __parse_cls_flower(priv, flow, spec, f, filter_dev, 3173 &inner_match_level, &outer_match_level); 3174 non_tunnel_match_level = (inner_match_level == MLX5_MATCH_NONE) ? 3175 outer_match_level : inner_match_level; 3176 3177 is_eswitch_flow = mlx5e_is_eswitch_flow(flow); 3178 if (!err && is_eswitch_flow) { 3179 rep = rpriv->rep; 3180 if (rep->vport != MLX5_VPORT_UPLINK && 3181 (esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE && 3182 esw->offloads.inline_mode < non_tunnel_match_level)) { 3183 NL_SET_ERR_MSG_MOD(extack, 3184 "Flow is not offloaded due to min inline setting"); 3185 netdev_warn(priv->netdev, 3186 "Flow is not offloaded due to min inline setting, required %d actual %d\n", 3187 non_tunnel_match_level, esw->offloads.inline_mode); 3188 return -EOPNOTSUPP; 3189 } 3190 } 3191 3192 flow->attr->inner_match_level = inner_match_level; 3193 flow->attr->outer_match_level = outer_match_level; 3194 3195 3196 return err; 3197} 3198 3199struct mlx5_fields { 3200 u8 field; 3201 u8 field_bsize; 3202 u32 field_mask; 3203 u32 offset; 3204 u32 match_offset; 3205}; 3206 3207#define OFFLOAD(fw_field, field_bsize, field_mask, field, off, match_field) \ 3208 {MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, field_bsize, field_mask, \ 3209 offsetof(struct pedit_headers, field) + (off), \ 3210 MLX5_BYTE_OFF(fte_match_set_lyr_2_4, match_field)} 3211 3212/* masked values are the same and there are no rewrites that do not have a 3213 * match. 3214 */ 3215#define SAME_VAL_MASK(type, valp, maskp, matchvalp, matchmaskp) ({ \ 3216 type matchmaskx = *(type *)(matchmaskp); \ 3217 type matchvalx = *(type *)(matchvalp); \ 3218 type maskx = *(type *)(maskp); \ 3219 type valx = *(type *)(valp); \ 3220 \ 3221 (valx & maskx) == (matchvalx & matchmaskx) && !(maskx & (maskx ^ \ 3222 matchmaskx)); \ 3223}) 3224 3225static bool cmp_val_mask(void *valp, void *maskp, void *matchvalp, 3226 void *matchmaskp, u8 bsize) 3227{ 3228 bool same = false; 3229 3230 switch (bsize) { 3231 case 8: 3232 same = SAME_VAL_MASK(u8, valp, maskp, matchvalp, matchmaskp); 3233 break; 3234 case 16: 3235 same = SAME_VAL_MASK(u16, valp, maskp, matchvalp, matchmaskp); 3236 break; 3237 case 32: 3238 same = SAME_VAL_MASK(u32, valp, maskp, matchvalp, matchmaskp); 3239 break; 3240 } 3241 3242 return same; 3243} 3244 3245static struct mlx5_fields fields[] = { 3246 OFFLOAD(DMAC_47_16, 32, U32_MAX, eth.h_dest[0], 0, dmac_47_16), 3247 OFFLOAD(DMAC_15_0, 16, U16_MAX, eth.h_dest[4], 0, dmac_15_0), 3248 OFFLOAD(SMAC_47_16, 32, U32_MAX, eth.h_source[0], 0, smac_47_16), 3249 OFFLOAD(SMAC_15_0, 16, U16_MAX, eth.h_source[4], 0, smac_15_0), 3250 OFFLOAD(ETHERTYPE, 16, U16_MAX, eth.h_proto, 0, ethertype), 3251 OFFLOAD(FIRST_VID, 16, U16_MAX, vlan.h_vlan_TCI, 0, first_vid), 3252 3253 OFFLOAD(IP_DSCP, 8, 0xfc, ip4.tos, 0, ip_dscp), 3254 OFFLOAD(IP_TTL, 8, U8_MAX, ip4.ttl, 0, ttl_hoplimit), 3255 OFFLOAD(SIPV4, 32, U32_MAX, ip4.saddr, 0, src_ipv4_src_ipv6.ipv4_layout.ipv4), 3256 OFFLOAD(DIPV4, 32, U32_MAX, ip4.daddr, 0, dst_ipv4_dst_ipv6.ipv4_layout.ipv4), 3257 3258 OFFLOAD(SIPV6_127_96, 32, U32_MAX, ip6.saddr.s6_addr32[0], 0, 3259 src_ipv4_src_ipv6.ipv6_layout.ipv6[0]), 3260 OFFLOAD(SIPV6_95_64, 32, U32_MAX, ip6.saddr.s6_addr32[1], 0, 3261 src_ipv4_src_ipv6.ipv6_layout.ipv6[4]), 3262 OFFLOAD(SIPV6_63_32, 32, U32_MAX, ip6.saddr.s6_addr32[2], 0, 3263 src_ipv4_src_ipv6.ipv6_layout.ipv6[8]), 3264 OFFLOAD(SIPV6_31_0, 32, U32_MAX, ip6.saddr.s6_addr32[3], 0, 3265 src_ipv4_src_ipv6.ipv6_layout.ipv6[12]), 3266 OFFLOAD(DIPV6_127_96, 32, U32_MAX, ip6.daddr.s6_addr32[0], 0, 3267 dst_ipv4_dst_ipv6.ipv6_layout.ipv6[0]), 3268 OFFLOAD(DIPV6_95_64, 32, U32_MAX, ip6.daddr.s6_addr32[1], 0, 3269 dst_ipv4_dst_ipv6.ipv6_layout.ipv6[4]), 3270 OFFLOAD(DIPV6_63_32, 32, U32_MAX, ip6.daddr.s6_addr32[2], 0, 3271 dst_ipv4_dst_ipv6.ipv6_layout.ipv6[8]), 3272 OFFLOAD(DIPV6_31_0, 32, U32_MAX, ip6.daddr.s6_addr32[3], 0, 3273 dst_ipv4_dst_ipv6.ipv6_layout.ipv6[12]), 3274 OFFLOAD(IPV6_HOPLIMIT, 8, U8_MAX, ip6.hop_limit, 0, ttl_hoplimit), 3275 OFFLOAD(IP_DSCP, 16, 0x0fc0, ip6, 0, ip_dscp), 3276 3277 OFFLOAD(TCP_SPORT, 16, U16_MAX, tcp.source, 0, tcp_sport), 3278 OFFLOAD(TCP_DPORT, 16, U16_MAX, tcp.dest, 0, tcp_dport), 3279 /* in linux iphdr tcp_flags is 8 bits long */ 3280 OFFLOAD(TCP_FLAGS, 8, U8_MAX, tcp.ack_seq, 5, tcp_flags), 3281 3282 OFFLOAD(UDP_SPORT, 16, U16_MAX, udp.source, 0, udp_sport), 3283 OFFLOAD(UDP_DPORT, 16, U16_MAX, udp.dest, 0, udp_dport), 3284}; 3285 3286static u32 mask_field_get(void *mask, struct mlx5_fields *f) 3287{ 3288 switch (f->field_bsize) { 3289 case 32: 3290 return be32_to_cpu(*(__be32 *)mask) & f->field_mask; 3291 case 16: 3292 return be16_to_cpu(*(__be16 *)mask) & (u16)f->field_mask; 3293 default: 3294 return *(u8 *)mask & (u8)f->field_mask; 3295 } 3296} 3297 3298static void mask_field_clear(void *mask, struct mlx5_fields *f) 3299{ 3300 switch (f->field_bsize) { 3301 case 32: 3302 *(__be32 *)mask &= ~cpu_to_be32(f->field_mask); 3303 break; 3304 case 16: 3305 *(__be16 *)mask &= ~cpu_to_be16((u16)f->field_mask); 3306 break; 3307 default: 3308 *(u8 *)mask &= ~(u8)f->field_mask; 3309 break; 3310 } 3311} 3312 3313static int offload_pedit_fields(struct mlx5e_priv *priv, 3314 int namespace, 3315 struct mlx5e_tc_flow_parse_attr *parse_attr, 3316 u32 *action_flags, 3317 struct netlink_ext_ack *extack) 3318{ 3319 struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals; 3320 struct pedit_headers_action *hdrs = parse_attr->hdrs; 3321 void *headers_c, *headers_v, *action, *vals_p; 3322 struct mlx5e_tc_mod_hdr_acts *mod_acts; 3323 void *s_masks_p, *a_masks_p; 3324 int i, first, last, next_z; 3325 struct mlx5_fields *f; 3326 unsigned long mask; 3327 u32 s_mask, a_mask; 3328 u8 cmd; 3329 3330 mod_acts = &parse_attr->mod_hdr_acts; 3331 headers_c = mlx5e_get_match_headers_criteria(*action_flags, &parse_attr->spec); 3332 headers_v = mlx5e_get_match_headers_value(*action_flags, &parse_attr->spec); 3333 3334 set_masks = &hdrs[TCA_PEDIT_KEY_EX_CMD_SET].masks; 3335 add_masks = &hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].masks; 3336 set_vals = &hdrs[TCA_PEDIT_KEY_EX_CMD_SET].vals; 3337 add_vals = &hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].vals; 3338 3339 for (i = 0; i < ARRAY_SIZE(fields); i++) { 3340 bool skip; 3341 3342 f = &fields[i]; 3343 s_masks_p = (void *)set_masks + f->offset; 3344 a_masks_p = (void *)add_masks + f->offset; 3345 3346 s_mask = mask_field_get(s_masks_p, f); 3347 a_mask = mask_field_get(a_masks_p, f); 3348 3349 if (!s_mask && !a_mask) /* nothing to offload here */ 3350 continue; 3351 3352 if (s_mask && a_mask) { 3353 NL_SET_ERR_MSG_MOD(extack, 3354 "can't set and add to the same HW field"); 3355 netdev_warn(priv->netdev, 3356 "mlx5: can't set and add to the same HW field (%x)\n", 3357 f->field); 3358 return -EOPNOTSUPP; 3359 } 3360 3361 skip = false; 3362 if (s_mask) { 3363 void *match_mask = headers_c + f->match_offset; 3364 void *match_val = headers_v + f->match_offset; 3365 3366 cmd = MLX5_ACTION_TYPE_SET; 3367 mask = s_mask; 3368 vals_p = (void *)set_vals + f->offset; 3369 /* don't rewrite if we have a match on the same value */ 3370 if (cmp_val_mask(vals_p, s_masks_p, match_val, 3371 match_mask, f->field_bsize)) 3372 skip = true; 3373 /* clear to denote we consumed this field */ 3374 mask_field_clear(s_masks_p, f); 3375 } else { 3376 cmd = MLX5_ACTION_TYPE_ADD; 3377 mask = a_mask; 3378 vals_p = (void *)add_vals + f->offset; 3379 /* add 0 is no change */ 3380 if (!mask_field_get(vals_p, f)) 3381 skip = true; 3382 /* clear to denote we consumed this field */ 3383 mask_field_clear(a_masks_p, f); 3384 } 3385 if (skip) 3386 continue; 3387 3388 first = find_first_bit(&mask, f->field_bsize); 3389 next_z = find_next_zero_bit(&mask, f->field_bsize, first); 3390 last = find_last_bit(&mask, f->field_bsize); 3391 if (first < next_z && next_z < last) { 3392 NL_SET_ERR_MSG_MOD(extack, 3393 "rewrite of few sub-fields isn't supported"); 3394 netdev_warn(priv->netdev, 3395 "mlx5: rewrite of few sub-fields (mask %lx) isn't offloaded\n", 3396 mask); 3397 return -EOPNOTSUPP; 3398 } 3399 3400 action = mlx5e_mod_hdr_alloc(priv->mdev, namespace, mod_acts); 3401 if (IS_ERR(action)) { 3402 NL_SET_ERR_MSG_MOD(extack, 3403 "too many pedit actions, can't offload"); 3404 mlx5_core_warn(priv->mdev, 3405 "mlx5: parsed %d pedit actions, can't do more\n", 3406 mod_acts->num_actions); 3407 return PTR_ERR(action); 3408 } 3409 3410 MLX5_SET(set_action_in, action, action_type, cmd); 3411 MLX5_SET(set_action_in, action, field, f->field); 3412 3413 if (cmd == MLX5_ACTION_TYPE_SET) { 3414 unsigned long field_mask = f->field_mask; 3415 int start; 3416 3417 /* if field is bit sized it can start not from first bit */ 3418 start = find_first_bit(&field_mask, f->field_bsize); 3419 3420 MLX5_SET(set_action_in, action, offset, first - start); 3421 /* length is num of bits to be written, zero means length of 32 */ 3422 MLX5_SET(set_action_in, action, length, (last - first + 1)); 3423 } 3424 3425 if (f->field_bsize == 32) 3426 MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p) >> first); 3427 else if (f->field_bsize == 16) 3428 MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p) >> first); 3429 else if (f->field_bsize == 8) 3430 MLX5_SET(set_action_in, action, data, *(u8 *)vals_p >> first); 3431 3432 ++mod_acts->num_actions; 3433 } 3434 3435 return 0; 3436} 3437 3438static const struct pedit_headers zero_masks = {}; 3439 3440static int verify_offload_pedit_fields(struct mlx5e_priv *priv, 3441 struct mlx5e_tc_flow_parse_attr *parse_attr, 3442 struct netlink_ext_ack *extack) 3443{ 3444 struct pedit_headers *cmd_masks; 3445 u8 cmd; 3446 3447 for (cmd = 0; cmd < __PEDIT_CMD_MAX; cmd++) { 3448 cmd_masks = &parse_attr->hdrs[cmd].masks; 3449 if (memcmp(cmd_masks, &zero_masks, sizeof(zero_masks))) { 3450 NL_SET_ERR_MSG_MOD(extack, "attempt to offload an unsupported field"); 3451 netdev_warn(priv->netdev, "attempt to offload an unsupported field (cmd %d)\n", cmd); 3452 print_hex_dump(KERN_WARNING, "mask: ", DUMP_PREFIX_ADDRESS, 3453 16, 1, cmd_masks, sizeof(zero_masks), true); 3454 return -EOPNOTSUPP; 3455 } 3456 } 3457 3458 return 0; 3459} 3460 3461static int alloc_tc_pedit_action(struct mlx5e_priv *priv, int namespace, 3462 struct mlx5e_tc_flow_parse_attr *parse_attr, 3463 u32 *action_flags, 3464 struct netlink_ext_ack *extack) 3465{ 3466 int err; 3467 3468 err = offload_pedit_fields(priv, namespace, parse_attr, action_flags, extack); 3469 if (err) 3470 goto out_dealloc_parsed_actions; 3471 3472 err = verify_offload_pedit_fields(priv, parse_attr, extack); 3473 if (err) 3474 goto out_dealloc_parsed_actions; 3475 3476 return 0; 3477 3478out_dealloc_parsed_actions: 3479 mlx5e_mod_hdr_dealloc(&parse_attr->mod_hdr_acts); 3480 return err; 3481} 3482 3483struct ip_ttl_word { 3484 __u8 ttl; 3485 __u8 protocol; 3486 __sum16 check; 3487}; 3488 3489struct ipv6_hoplimit_word { 3490 __be16 payload_len; 3491 __u8 nexthdr; 3492 __u8 hop_limit; 3493}; 3494 3495static bool 3496is_flow_action_modify_ip_header(struct flow_action *flow_action) 3497{ 3498 const struct flow_action_entry *act; 3499 u32 mask, offset; 3500 u8 htype; 3501 int i; 3502 3503 /* For IPv4 & IPv6 header check 4 byte word, 3504 * to determine that modified fields 3505 * are NOT ttl & hop_limit only. 3506 */ 3507 flow_action_for_each(i, act, flow_action) { 3508 if (act->id != FLOW_ACTION_MANGLE && 3509 act->id != FLOW_ACTION_ADD) 3510 continue; 3511 3512 htype = act->mangle.htype; 3513 offset = act->mangle.offset; 3514 mask = ~act->mangle.mask; 3515 3516 if (htype == FLOW_ACT_MANGLE_HDR_TYPE_IP4) { 3517 struct ip_ttl_word *ttl_word = 3518 (struct ip_ttl_word *)&mask; 3519 3520 if (offset != offsetof(struct iphdr, ttl) || 3521 ttl_word->protocol || 3522 ttl_word->check) 3523 return true; 3524 } else if (htype == FLOW_ACT_MANGLE_HDR_TYPE_IP6) { 3525 struct ipv6_hoplimit_word *hoplimit_word = 3526 (struct ipv6_hoplimit_word *)&mask; 3527 3528 if (offset != offsetof(struct ipv6hdr, payload_len) || 3529 hoplimit_word->payload_len || 3530 hoplimit_word->nexthdr) 3531 return true; 3532 } 3533 } 3534 3535 return false; 3536} 3537 3538static bool modify_header_match_supported(struct mlx5e_priv *priv, 3539 struct mlx5_flow_spec *spec, 3540 struct flow_action *flow_action, 3541 u32 actions, 3542 struct netlink_ext_ack *extack) 3543{ 3544 bool modify_ip_header; 3545 void *headers_c; 3546 void *headers_v; 3547 u16 ethertype; 3548 u8 ip_proto; 3549 3550 headers_c = mlx5e_get_match_headers_criteria(actions, spec); 3551 headers_v = mlx5e_get_match_headers_value(actions, spec); 3552 ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype); 3553 3554 /* for non-IP we only re-write MACs, so we're okay */ 3555 if (MLX5_GET(fte_match_set_lyr_2_4, headers_c, ip_version) == 0 && 3556 ethertype != ETH_P_IP && ethertype != ETH_P_IPV6) 3557 goto out_ok; 3558 3559 modify_ip_header = is_flow_action_modify_ip_header(flow_action); 3560 ip_proto = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ip_protocol); 3561 if (modify_ip_header && ip_proto != IPPROTO_TCP && 3562 ip_proto != IPPROTO_UDP && ip_proto != IPPROTO_ICMP) { 3563 NL_SET_ERR_MSG_MOD(extack, 3564 "can't offload re-write of non TCP/UDP"); 3565 netdev_info(priv->netdev, "can't offload re-write of ip proto %d\n", 3566 ip_proto); 3567 return false; 3568 } 3569 3570out_ok: 3571 return true; 3572} 3573 3574static bool 3575actions_match_supported_fdb(struct mlx5e_priv *priv, 3576 struct mlx5e_tc_flow *flow, 3577 struct netlink_ext_ack *extack) 3578{ 3579 struct mlx5_esw_flow_attr *esw_attr = flow->attr->esw_attr; 3580 3581 if (esw_attr->split_count > 0 && !mlx5_esw_has_fwd_fdb(priv->mdev)) { 3582 NL_SET_ERR_MSG_MOD(extack, 3583 "current firmware doesn't support split rule for port mirroring"); 3584 netdev_warn_once(priv->netdev, 3585 "current firmware doesn't support split rule for port mirroring\n"); 3586 return false; 3587 } 3588 3589 return true; 3590} 3591 3592static bool 3593actions_match_supported(struct mlx5e_priv *priv, 3594 struct flow_action *flow_action, 3595 u32 actions, 3596 struct mlx5e_tc_flow_parse_attr *parse_attr, 3597 struct mlx5e_tc_flow *flow, 3598 struct netlink_ext_ack *extack) 3599{ 3600 if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR && 3601 !modify_header_match_supported(priv, &parse_attr->spec, flow_action, actions, 3602 extack)) 3603 return false; 3604 3605 if (mlx5e_is_eswitch_flow(flow) && 3606 !actions_match_supported_fdb(priv, flow, extack)) 3607 return false; 3608 3609 return true; 3610} 3611 3612static bool same_port_devs(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv) 3613{ 3614 return priv->mdev == peer_priv->mdev; 3615} 3616 3617bool mlx5e_same_hw_devs(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv) 3618{ 3619 struct mlx5_core_dev *fmdev, *pmdev; 3620 3621 fmdev = priv->mdev; 3622 pmdev = peer_priv->mdev; 3623 3624 return mlx5_same_hw_devs(fmdev, pmdev); 3625} 3626 3627static int 3628actions_prepare_mod_hdr_actions(struct mlx5e_priv *priv, 3629 struct mlx5e_tc_flow *flow, 3630 struct mlx5_flow_attr *attr, 3631 struct netlink_ext_ack *extack) 3632{ 3633 struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr; 3634 struct pedit_headers_action *hdrs = parse_attr->hdrs; 3635 enum mlx5_flow_namespace_type ns_type; 3636 int err; 3637 3638 if (!hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits && 3639 !hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) 3640 return 0; 3641 3642 ns_type = mlx5e_get_flow_namespace(flow); 3643 3644 err = alloc_tc_pedit_action(priv, ns_type, parse_attr, &attr->action, extack); 3645 if (err) 3646 return err; 3647 3648 if (parse_attr->mod_hdr_acts.num_actions > 0) 3649 return 0; 3650 3651 /* In case all pedit actions are skipped, remove the MOD_HDR flag. */ 3652 attr->action &= ~MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 3653 mlx5e_mod_hdr_dealloc(&parse_attr->mod_hdr_acts); 3654 3655 if (ns_type != MLX5_FLOW_NAMESPACE_FDB) 3656 return 0; 3657 3658 if (!((attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP) || 3659 (attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH))) 3660 attr->esw_attr->split_count = 0; 3661 3662 return 0; 3663} 3664 3665static struct mlx5_flow_attr* 3666mlx5e_clone_flow_attr_for_post_act(struct mlx5_flow_attr *attr, 3667 enum mlx5_flow_namespace_type ns_type) 3668{ 3669 struct mlx5e_tc_flow_parse_attr *parse_attr; 3670 u32 attr_sz = ns_to_attr_sz(ns_type); 3671 struct mlx5_flow_attr *attr2; 3672 3673 attr2 = mlx5_alloc_flow_attr(ns_type); 3674 parse_attr = kvzalloc(sizeof(*parse_attr), GFP_KERNEL); 3675 if (!attr2 || !parse_attr) { 3676 kvfree(parse_attr); 3677 kfree(attr2); 3678 return NULL; 3679 } 3680 3681 memcpy(attr2, attr, attr_sz); 3682 INIT_LIST_HEAD(&attr2->list); 3683 parse_attr->filter_dev = attr->parse_attr->filter_dev; 3684 attr2->action = 0; 3685 attr2->counter = NULL; 3686 attr2->tc_act_cookies_count = 0; 3687 attr2->flags = 0; 3688 attr2->parse_attr = parse_attr; 3689 attr2->dest_chain = 0; 3690 attr2->dest_ft = NULL; 3691 attr2->act_id_restore_rule = NULL; 3692 memset(&attr2->ct_attr, 0, sizeof(attr2->ct_attr)); 3693 3694 if (ns_type == MLX5_FLOW_NAMESPACE_FDB) { 3695 attr2->esw_attr->out_count = 0; 3696 attr2->esw_attr->split_count = 0; 3697 } 3698 3699 attr2->branch_true = NULL; 3700 attr2->branch_false = NULL; 3701 attr2->jumping_attr = NULL; 3702 return attr2; 3703} 3704 3705struct mlx5_flow_attr * 3706mlx5e_tc_get_encap_attr(struct mlx5e_tc_flow *flow) 3707{ 3708 struct mlx5_esw_flow_attr *esw_attr; 3709 struct mlx5_flow_attr *attr; 3710 int i; 3711 3712 list_for_each_entry(attr, &flow->attrs, list) { 3713 esw_attr = attr->esw_attr; 3714 for (i = 0; i < MLX5_MAX_FLOW_FWD_VPORTS; i++) { 3715 if (esw_attr->dests[i].flags & MLX5_ESW_DEST_ENCAP) 3716 return attr; 3717 } 3718 } 3719 3720 return NULL; 3721} 3722 3723void 3724mlx5e_tc_unoffload_flow_post_acts(struct mlx5e_tc_flow *flow) 3725{ 3726 struct mlx5e_post_act *post_act = get_post_action(flow->priv); 3727 struct mlx5_flow_attr *attr; 3728 3729 list_for_each_entry(attr, &flow->attrs, list) { 3730 if (list_is_last(&attr->list, &flow->attrs)) 3731 break; 3732 3733 mlx5e_tc_post_act_unoffload(post_act, attr->post_act_handle); 3734 } 3735} 3736 3737static void 3738free_flow_post_acts(struct mlx5e_tc_flow *flow) 3739{ 3740 struct mlx5_flow_attr *attr, *tmp; 3741 3742 list_for_each_entry_safe(attr, tmp, &flow->attrs, list) { 3743 if (list_is_last(&attr->list, &flow->attrs)) 3744 break; 3745 3746 mlx5_free_flow_attr_actions(flow, attr); 3747 3748 list_del(&attr->list); 3749 kvfree(attr->parse_attr); 3750 kfree(attr); 3751 } 3752} 3753 3754int 3755mlx5e_tc_offload_flow_post_acts(struct mlx5e_tc_flow *flow) 3756{ 3757 struct mlx5e_post_act *post_act = get_post_action(flow->priv); 3758 struct mlx5_flow_attr *attr; 3759 int err = 0; 3760 3761 list_for_each_entry(attr, &flow->attrs, list) { 3762 if (list_is_last(&attr->list, &flow->attrs)) 3763 break; 3764 3765 err = mlx5e_tc_post_act_offload(post_act, attr->post_act_handle); 3766 if (err) 3767 break; 3768 } 3769 3770 return err; 3771} 3772 3773/* TC filter rule HW translation: 3774 * 3775 * +---------------------+ 3776 * + ft prio (tc chain) + 3777 * + original match + 3778 * +---------------------+ 3779 * | 3780 * | if multi table action 3781 * | 3782 * v 3783 * +---------------------+ 3784 * + post act ft |<----. 3785 * + match fte id | | split on multi table action 3786 * + do actions |-----' 3787 * +---------------------+ 3788 * | 3789 * | 3790 * v 3791 * Do rest of the actions after last multi table action. 3792 */ 3793static int 3794alloc_flow_post_acts(struct mlx5e_tc_flow *flow, struct netlink_ext_ack *extack) 3795{ 3796 struct mlx5e_post_act *post_act = get_post_action(flow->priv); 3797 struct mlx5_flow_attr *attr, *next_attr = NULL; 3798 struct mlx5e_post_act_handle *handle; 3799 int err; 3800 3801 /* This is going in reverse order as needed. 3802 * The first entry is the last attribute. 3803 */ 3804 list_for_each_entry(attr, &flow->attrs, list) { 3805 if (!next_attr) { 3806 /* Set counter action on last post act rule. */ 3807 attr->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; 3808 } 3809 3810 if (next_attr && !(attr->flags & MLX5_ATTR_FLAG_TERMINATING)) { 3811 err = mlx5e_tc_act_set_next_post_act(flow, attr, next_attr); 3812 if (err) 3813 goto out_free; 3814 } 3815 3816 /* Don't add post_act rule for first attr (last in the list). 3817 * It's being handled by the caller. 3818 */ 3819 if (list_is_last(&attr->list, &flow->attrs)) 3820 break; 3821 3822 err = actions_prepare_mod_hdr_actions(flow->priv, flow, attr, extack); 3823 if (err) 3824 goto out_free; 3825 3826 err = post_process_attr(flow, attr, extack); 3827 if (err) 3828 goto out_free; 3829 3830 handle = mlx5e_tc_post_act_add(post_act, attr); 3831 if (IS_ERR(handle)) { 3832 err = PTR_ERR(handle); 3833 goto out_free; 3834 } 3835 3836 attr->post_act_handle = handle; 3837 3838 if (attr->jumping_attr) { 3839 err = mlx5e_tc_act_set_next_post_act(flow, attr->jumping_attr, attr); 3840 if (err) 3841 goto out_free; 3842 } 3843 3844 next_attr = attr; 3845 } 3846 3847 if (flow_flag_test(flow, SLOW)) 3848 goto out; 3849 3850 err = mlx5e_tc_offload_flow_post_acts(flow); 3851 if (err) 3852 goto out_free; 3853 3854out: 3855 return 0; 3856 3857out_free: 3858 free_flow_post_acts(flow); 3859 return err; 3860} 3861 3862static int 3863set_branch_dest_ft(struct mlx5e_priv *priv, struct mlx5_flow_attr *attr) 3864{ 3865 struct mlx5e_post_act *post_act = get_post_action(priv); 3866 3867 if (IS_ERR(post_act)) 3868 return PTR_ERR(post_act); 3869 3870 attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 3871 attr->dest_ft = mlx5e_tc_post_act_get_ft(post_act); 3872 3873 return 0; 3874} 3875 3876static int 3877alloc_branch_attr(struct mlx5e_tc_flow *flow, 3878 struct mlx5e_tc_act_branch_ctrl *cond, 3879 struct mlx5_flow_attr **cond_attr, 3880 u32 *jump_count, 3881 struct netlink_ext_ack *extack) 3882{ 3883 struct mlx5_flow_attr *attr; 3884 int err = 0; 3885 3886 *cond_attr = mlx5e_clone_flow_attr_for_post_act(flow->attr, 3887 mlx5e_get_flow_namespace(flow)); 3888 if (!(*cond_attr)) 3889 return -ENOMEM; 3890 3891 attr = *cond_attr; 3892 3893 switch (cond->act_id) { 3894 case FLOW_ACTION_DROP: 3895 attr->action |= MLX5_FLOW_CONTEXT_ACTION_DROP; 3896 break; 3897 case FLOW_ACTION_ACCEPT: 3898 case FLOW_ACTION_PIPE: 3899 err = set_branch_dest_ft(flow->priv, attr); 3900 if (err) 3901 goto out_err; 3902 break; 3903 case FLOW_ACTION_JUMP: 3904 if (*jump_count) { 3905 NL_SET_ERR_MSG_MOD(extack, "Cannot offload flows with nested jumps"); 3906 err = -EOPNOTSUPP; 3907 goto out_err; 3908 } 3909 *jump_count = cond->extval; 3910 err = set_branch_dest_ft(flow->priv, attr); 3911 if (err) 3912 goto out_err; 3913 break; 3914 default: 3915 err = -EOPNOTSUPP; 3916 goto out_err; 3917 } 3918 3919 return err; 3920out_err: 3921 kfree(*cond_attr); 3922 *cond_attr = NULL; 3923 return err; 3924} 3925 3926static void 3927dec_jump_count(struct flow_action_entry *act, struct mlx5e_tc_act *tc_act, 3928 struct mlx5_flow_attr *attr, struct mlx5e_priv *priv, 3929 struct mlx5e_tc_jump_state *jump_state) 3930{ 3931 if (!jump_state->jump_count) 3932 return; 3933 3934 /* Single tc action can instantiate multiple offload actions (e.g. pedit) 3935 * Jump only over a tc action 3936 */ 3937 if (act->id == jump_state->last_id && act->hw_index == jump_state->last_index) 3938 return; 3939 3940 jump_state->last_id = act->id; 3941 jump_state->last_index = act->hw_index; 3942 3943 /* nothing to do for intermediate actions */ 3944 if (--jump_state->jump_count > 1) 3945 return; 3946 3947 if (jump_state->jump_count == 1) { /* last action in the jump action list */ 3948 3949 /* create a new attribute after this action */ 3950 jump_state->jump_target = true; 3951 3952 if (tc_act->is_terminating_action) { /* the branch ends here */ 3953 attr->flags |= MLX5_ATTR_FLAG_TERMINATING; 3954 attr->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; 3955 } else { /* the branch continues executing the rest of the actions */ 3956 struct mlx5e_post_act *post_act; 3957 3958 attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 3959 post_act = get_post_action(priv); 3960 attr->dest_ft = mlx5e_tc_post_act_get_ft(post_act); 3961 } 3962 } else if (jump_state->jump_count == 0) { /* first attr after the jump action list */ 3963 /* This is the post action for the jumping attribute (either red or green) 3964 * Use the stored jumping_attr to set the post act id on the jumping attribute 3965 */ 3966 attr->jumping_attr = jump_state->jumping_attr; 3967 } 3968} 3969 3970static int 3971parse_branch_ctrl(struct flow_action_entry *act, struct mlx5e_tc_act *tc_act, 3972 struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr, 3973 struct mlx5e_tc_jump_state *jump_state, 3974 struct netlink_ext_ack *extack) 3975{ 3976 struct mlx5e_tc_act_branch_ctrl cond_true, cond_false; 3977 u32 jump_count = jump_state->jump_count; 3978 int err; 3979 3980 if (!tc_act->get_branch_ctrl) 3981 return 0; 3982 3983 tc_act->get_branch_ctrl(act, &cond_true, &cond_false); 3984 3985 err = alloc_branch_attr(flow, &cond_true, 3986 &attr->branch_true, &jump_count, extack); 3987 if (err) 3988 goto out_err; 3989 3990 if (jump_count) 3991 jump_state->jumping_attr = attr->branch_true; 3992 3993 err = alloc_branch_attr(flow, &cond_false, 3994 &attr->branch_false, &jump_count, extack); 3995 if (err) 3996 goto err_branch_false; 3997 3998 if (jump_count && !jump_state->jumping_attr) 3999 jump_state->jumping_attr = attr->branch_false; 4000 4001 jump_state->jump_count = jump_count; 4002 4003 /* branching action requires its own counter */ 4004 attr->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; 4005 flow_flag_set(flow, USE_ACT_STATS); 4006 4007 return 0; 4008 4009err_branch_false: 4010 free_branch_attr(flow, attr->branch_true); 4011out_err: 4012 return err; 4013} 4014 4015static int 4016parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state, 4017 struct flow_action *flow_action) 4018{ 4019 struct netlink_ext_ack *extack = parse_state->extack; 4020 struct mlx5e_tc_flow *flow = parse_state->flow; 4021 struct mlx5e_tc_jump_state jump_state = {}; 4022 struct mlx5_flow_attr *attr = flow->attr; 4023 enum mlx5_flow_namespace_type ns_type; 4024 struct mlx5e_priv *priv = flow->priv; 4025 struct mlx5_flow_attr *prev_attr; 4026 struct flow_action_entry *act; 4027 struct mlx5e_tc_act *tc_act; 4028 int err, i, i_split = 0; 4029 bool is_missable; 4030 4031 ns_type = mlx5e_get_flow_namespace(flow); 4032 list_add(&attr->list, &flow->attrs); 4033 4034 flow_action_for_each(i, act, flow_action) { 4035 jump_state.jump_target = false; 4036 is_missable = false; 4037 prev_attr = attr; 4038 4039 tc_act = mlx5e_tc_act_get(act->id, ns_type); 4040 if (!tc_act) { 4041 NL_SET_ERR_MSG_MOD(extack, "Not implemented offload action"); 4042 err = -EOPNOTSUPP; 4043 goto out_free_post_acts; 4044 } 4045 4046 if (tc_act->can_offload && !tc_act->can_offload(parse_state, act, i, attr)) { 4047 err = -EOPNOTSUPP; 4048 goto out_free_post_acts; 4049 } 4050 4051 err = tc_act->parse_action(parse_state, act, priv, attr); 4052 if (err) 4053 goto out_free_post_acts; 4054 4055 dec_jump_count(act, tc_act, attr, priv, &jump_state); 4056 4057 err = parse_branch_ctrl(act, tc_act, flow, attr, &jump_state, extack); 4058 if (err) 4059 goto out_free_post_acts; 4060 4061 parse_state->actions |= attr->action; 4062 4063 /* Split attr for multi table act if not the last act. */ 4064 if (jump_state.jump_target || 4065 (tc_act->is_multi_table_act && 4066 tc_act->is_multi_table_act(priv, act, attr) && 4067 i < flow_action->num_entries - 1)) { 4068 is_missable = tc_act->is_missable ? tc_act->is_missable(act) : false; 4069 4070 err = mlx5e_tc_act_post_parse(parse_state, flow_action, i_split, i, attr, 4071 ns_type); 4072 if (err) 4073 goto out_free_post_acts; 4074 4075 attr = mlx5e_clone_flow_attr_for_post_act(flow->attr, ns_type); 4076 if (!attr) { 4077 err = -ENOMEM; 4078 goto out_free_post_acts; 4079 } 4080 4081 i_split = i + 1; 4082 parse_state->if_count = 0; 4083 list_add(&attr->list, &flow->attrs); 4084 } 4085 4086 if (is_missable) { 4087 /* Add counter to prev, and assign act to new (next) attr */ 4088 prev_attr->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; 4089 flow_flag_set(flow, USE_ACT_STATS); 4090 4091 attr->tc_act_cookies[attr->tc_act_cookies_count++] = act->cookie; 4092 } else if (!tc_act->stats_action) { 4093 prev_attr->tc_act_cookies[prev_attr->tc_act_cookies_count++] = act->cookie; 4094 } 4095 } 4096 4097 err = mlx5e_tc_act_post_parse(parse_state, flow_action, i_split, i, attr, ns_type); 4098 if (err) 4099 goto out_free_post_acts; 4100 4101 err = alloc_flow_post_acts(flow, extack); 4102 if (err) 4103 goto out_free_post_acts; 4104 4105 return 0; 4106 4107out_free_post_acts: 4108 free_flow_post_acts(flow); 4109 4110 return err; 4111} 4112 4113static int 4114flow_action_supported(struct flow_action *flow_action, 4115 struct netlink_ext_ack *extack) 4116{ 4117 if (!flow_action_has_entries(flow_action)) { 4118 NL_SET_ERR_MSG_MOD(extack, "Flow action doesn't have any entries"); 4119 return -EINVAL; 4120 } 4121 4122 if (!flow_action_hw_stats_check(flow_action, extack, 4123 FLOW_ACTION_HW_STATS_DELAYED_BIT)) { 4124 NL_SET_ERR_MSG_MOD(extack, "Flow action HW stats type is not supported"); 4125 return -EOPNOTSUPP; 4126 } 4127 4128 return 0; 4129} 4130 4131static int 4132parse_tc_nic_actions(struct mlx5e_priv *priv, 4133 struct flow_action *flow_action, 4134 struct mlx5e_tc_flow *flow, 4135 struct netlink_ext_ack *extack) 4136{ 4137 struct mlx5e_tc_act_parse_state *parse_state; 4138 struct mlx5e_tc_flow_parse_attr *parse_attr; 4139 struct mlx5_flow_attr *attr = flow->attr; 4140 int err; 4141 4142 err = flow_action_supported(flow_action, extack); 4143 if (err) 4144 return err; 4145 4146 attr->nic_attr->flow_tag = MLX5_FS_DEFAULT_FLOW_TAG; 4147 parse_attr = attr->parse_attr; 4148 parse_state = &parse_attr->parse_state; 4149 mlx5e_tc_act_init_parse_state(parse_state, flow, flow_action, extack); 4150 parse_state->ct_priv = get_ct_priv(priv); 4151 4152 err = parse_tc_actions(parse_state, flow_action); 4153 if (err) 4154 return err; 4155 4156 err = actions_prepare_mod_hdr_actions(priv, flow, attr, extack); 4157 if (err) 4158 return err; 4159 4160 err = verify_attr_actions(attr->action, extack); 4161 if (err) 4162 return err; 4163 4164 if (!actions_match_supported(priv, flow_action, parse_state->actions, 4165 parse_attr, flow, extack)) 4166 return -EOPNOTSUPP; 4167 4168 return 0; 4169} 4170 4171static bool is_merged_eswitch_vfs(struct mlx5e_priv *priv, 4172 struct net_device *peer_netdev) 4173{ 4174 struct mlx5e_priv *peer_priv; 4175 4176 peer_priv = netdev_priv(peer_netdev); 4177 4178 return (MLX5_CAP_ESW(priv->mdev, merged_eswitch) && 4179 mlx5e_eswitch_vf_rep(priv->netdev) && 4180 mlx5e_eswitch_vf_rep(peer_netdev) && 4181 mlx5e_same_hw_devs(priv, peer_priv)); 4182} 4183 4184static bool same_hw_reps(struct mlx5e_priv *priv, 4185 struct net_device *peer_netdev) 4186{ 4187 struct mlx5e_priv *peer_priv; 4188 4189 peer_priv = netdev_priv(peer_netdev); 4190 4191 return mlx5e_eswitch_rep(priv->netdev) && 4192 mlx5e_eswitch_rep(peer_netdev) && 4193 mlx5e_same_hw_devs(priv, peer_priv); 4194} 4195 4196static bool is_lag_dev(struct mlx5e_priv *priv, 4197 struct net_device *peer_netdev) 4198{ 4199 return ((mlx5_lag_is_sriov(priv->mdev) || 4200 mlx5_lag_is_multipath(priv->mdev)) && 4201 same_hw_reps(priv, peer_netdev)); 4202} 4203 4204static bool is_multiport_eligible(struct mlx5e_priv *priv, struct net_device *out_dev) 4205{ 4206 return same_hw_reps(priv, out_dev) && mlx5_lag_is_mpesw(priv->mdev); 4207} 4208 4209bool mlx5e_is_valid_eswitch_fwd_dev(struct mlx5e_priv *priv, 4210 struct net_device *out_dev) 4211{ 4212 if (is_merged_eswitch_vfs(priv, out_dev)) 4213 return true; 4214 4215 if (is_multiport_eligible(priv, out_dev)) 4216 return true; 4217 4218 if (is_lag_dev(priv, out_dev)) 4219 return true; 4220 4221 return mlx5e_eswitch_rep(out_dev) && 4222 same_port_devs(priv, netdev_priv(out_dev)); 4223} 4224 4225int mlx5e_set_fwd_to_int_port_actions(struct mlx5e_priv *priv, 4226 struct mlx5_flow_attr *attr, 4227 int ifindex, 4228 enum mlx5e_tc_int_port_type type, 4229 u32 *action, 4230 int out_index) 4231{ 4232 struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr; 4233 struct mlx5e_tc_int_port_priv *int_port_priv; 4234 struct mlx5e_tc_flow_parse_attr *parse_attr; 4235 struct mlx5e_tc_int_port *dest_int_port; 4236 int err; 4237 4238 parse_attr = attr->parse_attr; 4239 int_port_priv = mlx5e_get_int_port_priv(priv); 4240 4241 dest_int_port = mlx5e_tc_int_port_get(int_port_priv, ifindex, type); 4242 if (IS_ERR(dest_int_port)) 4243 return PTR_ERR(dest_int_port); 4244 4245 err = mlx5e_tc_match_to_reg_set(priv->mdev, &parse_attr->mod_hdr_acts, 4246 MLX5_FLOW_NAMESPACE_FDB, VPORT_TO_REG, 4247 mlx5e_tc_int_port_get_metadata(dest_int_port)); 4248 if (err) { 4249 mlx5e_tc_int_port_put(int_port_priv, dest_int_port); 4250 return err; 4251 } 4252 4253 *action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 4254 4255 esw_attr->dest_int_port = dest_int_port; 4256 esw_attr->dests[out_index].flags |= MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE; 4257 esw_attr->split_count = out_index; 4258 4259 /* Forward to root fdb for matching against the new source vport */ 4260 attr->dest_chain = 0; 4261 4262 return 0; 4263} 4264 4265static int 4266parse_tc_fdb_actions(struct mlx5e_priv *priv, 4267 struct flow_action *flow_action, 4268 struct mlx5e_tc_flow *flow, 4269 struct netlink_ext_ack *extack) 4270{ 4271 struct mlx5e_tc_act_parse_state *parse_state; 4272 struct mlx5e_tc_flow_parse_attr *parse_attr; 4273 struct mlx5_flow_attr *attr = flow->attr; 4274 struct mlx5_esw_flow_attr *esw_attr; 4275 struct net_device *filter_dev; 4276 int err; 4277 4278 err = flow_action_supported(flow_action, extack); 4279 if (err) 4280 return err; 4281 4282 esw_attr = attr->esw_attr; 4283 parse_attr = attr->parse_attr; 4284 filter_dev = parse_attr->filter_dev; 4285 parse_state = &parse_attr->parse_state; 4286 mlx5e_tc_act_init_parse_state(parse_state, flow, flow_action, extack); 4287 parse_state->ct_priv = get_ct_priv(priv); 4288 4289 err = parse_tc_actions(parse_state, flow_action); 4290 if (err) 4291 return err; 4292 4293 /* Forward to/from internal port can only have 1 dest */ 4294 if ((netif_is_ovs_master(filter_dev) || esw_attr->dest_int_port) && 4295 esw_attr->out_count > 1) { 4296 NL_SET_ERR_MSG_MOD(extack, 4297 "Rules with internal port can have only one destination"); 4298 return -EOPNOTSUPP; 4299 } 4300 4301 /* Forward from tunnel/internal port to internal port is not supported */ 4302 if ((mlx5e_get_tc_tun(filter_dev) || netif_is_ovs_master(filter_dev)) && 4303 esw_attr->dest_int_port) { 4304 NL_SET_ERR_MSG_MOD(extack, 4305 "Forwarding from tunnel/internal port to internal port is not supported"); 4306 return -EOPNOTSUPP; 4307 } 4308 4309 err = actions_prepare_mod_hdr_actions(priv, flow, attr, extack); 4310 if (err) 4311 return err; 4312 4313 if (!actions_match_supported(priv, flow_action, parse_state->actions, 4314 parse_attr, flow, extack)) 4315 return -EOPNOTSUPP; 4316 4317 return 0; 4318} 4319 4320static void get_flags(int flags, unsigned long *flow_flags) 4321{ 4322 unsigned long __flow_flags = 0; 4323 4324 if (flags & MLX5_TC_FLAG(INGRESS)) 4325 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_INGRESS); 4326 if (flags & MLX5_TC_FLAG(EGRESS)) 4327 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_EGRESS); 4328 4329 if (flags & MLX5_TC_FLAG(ESW_OFFLOAD)) 4330 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_ESWITCH); 4331 if (flags & MLX5_TC_FLAG(NIC_OFFLOAD)) 4332 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_NIC); 4333 if (flags & MLX5_TC_FLAG(FT_OFFLOAD)) 4334 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_FT); 4335 4336 *flow_flags = __flow_flags; 4337} 4338 4339static const struct rhashtable_params tc_ht_params = { 4340 .head_offset = offsetof(struct mlx5e_tc_flow, node), 4341 .key_offset = offsetof(struct mlx5e_tc_flow, cookie), 4342 .key_len = sizeof(((struct mlx5e_tc_flow *)0)->cookie), 4343 .automatic_shrinking = true, 4344}; 4345 4346static struct rhashtable *get_tc_ht(struct mlx5e_priv *priv, 4347 unsigned long flags) 4348{ 4349 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 4350 struct mlx5e_rep_priv *rpriv; 4351 4352 if (flags & MLX5_TC_FLAG(ESW_OFFLOAD)) { 4353 rpriv = priv->ppriv; 4354 return &rpriv->tc_ht; 4355 } else /* NIC offload */ 4356 return &tc->ht; 4357} 4358 4359static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow) 4360{ 4361 struct mlx5_esw_flow_attr *esw_attr = flow->attr->esw_attr; 4362 struct mlx5_flow_attr *attr = flow->attr; 4363 bool is_rep_ingress = esw_attr->in_rep->vport != MLX5_VPORT_UPLINK && 4364 flow_flag_test(flow, INGRESS); 4365 bool act_is_encap = !!(attr->action & 4366 MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT); 4367 bool esw_paired = mlx5_devcom_comp_is_ready(esw_attr->in_mdev->priv.eswitch->devcom); 4368 4369 if (!esw_paired) 4370 return false; 4371 4372 if ((mlx5_lag_is_sriov(esw_attr->in_mdev) || 4373 mlx5_lag_is_multipath(esw_attr->in_mdev)) && 4374 (is_rep_ingress || act_is_encap)) 4375 return true; 4376 4377 if (mlx5_lag_is_mpesw(esw_attr->in_mdev)) 4378 return true; 4379 4380 return false; 4381} 4382 4383struct mlx5_flow_attr * 4384mlx5_alloc_flow_attr(enum mlx5_flow_namespace_type type) 4385{ 4386 u32 ex_attr_size = (type == MLX5_FLOW_NAMESPACE_FDB) ? 4387 sizeof(struct mlx5_esw_flow_attr) : 4388 sizeof(struct mlx5_nic_flow_attr); 4389 struct mlx5_flow_attr *attr; 4390 4391 attr = kzalloc(sizeof(*attr) + ex_attr_size, GFP_KERNEL); 4392 if (!attr) 4393 return attr; 4394 4395 INIT_LIST_HEAD(&attr->list); 4396 return attr; 4397} 4398 4399static void 4400mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr) 4401{ 4402 struct mlx5_core_dev *counter_dev = get_flow_counter_dev(flow); 4403 struct mlx5_esw_flow_attr *esw_attr; 4404 4405 if (!attr) 4406 return; 4407 4408 if (attr->post_act_handle) 4409 mlx5e_tc_post_act_del(get_post_action(flow->priv), attr->post_act_handle); 4410 4411 mlx5e_tc_tun_encap_dests_unset(flow->priv, flow, attr); 4412 4413 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) 4414 mlx5_fc_destroy(counter_dev, attr->counter); 4415 4416 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { 4417 mlx5e_mod_hdr_dealloc(&attr->parse_attr->mod_hdr_acts); 4418 mlx5e_tc_detach_mod_hdr(flow->priv, flow, attr); 4419 } 4420 4421 if (mlx5e_is_eswitch_flow(flow)) { 4422 esw_attr = attr->esw_attr; 4423 4424 if (esw_attr->int_port) 4425 mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(flow->priv), 4426 esw_attr->int_port); 4427 4428 if (esw_attr->dest_int_port) 4429 mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(flow->priv), 4430 esw_attr->dest_int_port); 4431 } 4432 4433 mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), attr); 4434 4435 free_branch_attr(flow, attr->branch_true); 4436 free_branch_attr(flow, attr->branch_false); 4437} 4438 4439static int 4440mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size, 4441 struct flow_cls_offload *f, unsigned long flow_flags, 4442 struct mlx5e_tc_flow_parse_attr **__parse_attr, 4443 struct mlx5e_tc_flow **__flow) 4444{ 4445 struct mlx5e_tc_flow_parse_attr *parse_attr; 4446 struct mlx5_flow_attr *attr; 4447 struct mlx5e_tc_flow *flow; 4448 int err = -ENOMEM; 4449 int out_index; 4450 4451 flow = kzalloc(sizeof(*flow), GFP_KERNEL); 4452 parse_attr = kvzalloc(sizeof(*parse_attr), GFP_KERNEL); 4453 if (!parse_attr || !flow) 4454 goto err_free; 4455 4456 flow->flags = flow_flags; 4457 flow->cookie = f->cookie; 4458 flow->priv = priv; 4459 4460 attr = mlx5_alloc_flow_attr(mlx5e_get_flow_namespace(flow)); 4461 if (!attr) 4462 goto err_free; 4463 4464 flow->attr = attr; 4465 4466 for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) 4467 INIT_LIST_HEAD(&flow->encaps[out_index].list); 4468 INIT_LIST_HEAD(&flow->hairpin); 4469 INIT_LIST_HEAD(&flow->l3_to_l2_reformat); 4470 INIT_LIST_HEAD(&flow->attrs); 4471 INIT_LIST_HEAD(&flow->peer_flows); 4472 refcount_set(&flow->refcnt, 1); 4473 init_completion(&flow->init_done); 4474 init_completion(&flow->del_hw_done); 4475 4476 *__flow = flow; 4477 *__parse_attr = parse_attr; 4478 4479 return 0; 4480 4481err_free: 4482 kfree(flow); 4483 kvfree(parse_attr); 4484 return err; 4485} 4486 4487static void 4488mlx5e_flow_attr_init(struct mlx5_flow_attr *attr, 4489 struct mlx5e_tc_flow_parse_attr *parse_attr, 4490 struct flow_cls_offload *f) 4491{ 4492 attr->parse_attr = parse_attr; 4493 attr->chain = f->common.chain_index; 4494 attr->prio = f->common.prio; 4495} 4496 4497static void 4498mlx5e_flow_esw_attr_init(struct mlx5_flow_attr *attr, 4499 struct mlx5e_priv *priv, 4500 struct mlx5e_tc_flow_parse_attr *parse_attr, 4501 struct flow_cls_offload *f, 4502 struct mlx5_eswitch_rep *in_rep, 4503 struct mlx5_core_dev *in_mdev) 4504{ 4505 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 4506 struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr; 4507 4508 mlx5e_flow_attr_init(attr, parse_attr, f); 4509 4510 esw_attr->in_rep = in_rep; 4511 esw_attr->in_mdev = in_mdev; 4512 4513 if (MLX5_CAP_ESW(esw->dev, counter_eswitch_affinity) == 4514 MLX5_COUNTER_SOURCE_ESWITCH) 4515 esw_attr->counter_dev = in_mdev; 4516 else 4517 esw_attr->counter_dev = priv->mdev; 4518} 4519 4520static struct mlx5e_tc_flow * 4521__mlx5e_add_fdb_flow(struct mlx5e_priv *priv, 4522 struct flow_cls_offload *f, 4523 unsigned long flow_flags, 4524 struct net_device *filter_dev, 4525 struct mlx5_eswitch_rep *in_rep, 4526 struct mlx5_core_dev *in_mdev) 4527{ 4528 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 4529 struct netlink_ext_ack *extack = f->common.extack; 4530 struct mlx5e_tc_flow_parse_attr *parse_attr; 4531 struct mlx5e_tc_flow *flow; 4532 int attr_size, err; 4533 4534 flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_ESWITCH); 4535 attr_size = sizeof(struct mlx5_esw_flow_attr); 4536 err = mlx5e_alloc_flow(priv, attr_size, f, flow_flags, 4537 &parse_attr, &flow); 4538 if (err) 4539 goto out; 4540 4541 parse_attr->filter_dev = filter_dev; 4542 mlx5e_flow_esw_attr_init(flow->attr, 4543 priv, parse_attr, 4544 f, in_rep, in_mdev); 4545 4546 err = parse_cls_flower(flow->priv, flow, &parse_attr->spec, 4547 f, filter_dev); 4548 if (err) 4549 goto err_free; 4550 4551 /* actions validation depends on parsing the ct matches first */ 4552 err = mlx5_tc_ct_match_add(get_ct_priv(priv), &parse_attr->spec, f, 4553 &flow->attr->ct_attr, extack); 4554 if (err) 4555 goto err_free; 4556 4557 err = parse_tc_fdb_actions(priv, &rule->action, flow, extack); 4558 if (err) 4559 goto err_free; 4560 4561 err = mlx5e_tc_add_fdb_flow(priv, flow, extack); 4562 complete_all(&flow->init_done); 4563 if (err) { 4564 if (!(err == -ENETUNREACH && mlx5_lag_is_multipath(in_mdev))) 4565 goto err_free; 4566 4567 add_unready_flow(flow); 4568 } 4569 4570 return flow; 4571 4572err_free: 4573 mlx5e_flow_put(priv, flow); 4574out: 4575 return ERR_PTR(err); 4576} 4577 4578static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f, 4579 struct mlx5e_tc_flow *flow, 4580 unsigned long flow_flags, 4581 struct mlx5_eswitch *peer_esw) 4582{ 4583 struct mlx5e_priv *priv = flow->priv, *peer_priv; 4584 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 4585 struct mlx5_esw_flow_attr *attr = flow->attr->esw_attr; 4586 struct mlx5e_tc_flow_parse_attr *parse_attr; 4587 int i = mlx5_get_dev_index(peer_esw->dev); 4588 struct mlx5e_rep_priv *peer_urpriv; 4589 struct mlx5e_tc_flow *peer_flow; 4590 struct mlx5_core_dev *in_mdev; 4591 int err = 0; 4592 4593 peer_urpriv = mlx5_eswitch_get_uplink_priv(peer_esw, REP_ETH); 4594 peer_priv = netdev_priv(peer_urpriv->netdev); 4595 4596 /* in_mdev is assigned of which the packet originated from. 4597 * So packets redirected to uplink use the same mdev of the 4598 * original flow and packets redirected from uplink use the 4599 * peer mdev. 4600 * In multiport eswitch it's a special case that we need to 4601 * keep the original mdev. 4602 */ 4603 if (attr->in_rep->vport == MLX5_VPORT_UPLINK && !mlx5_lag_is_mpesw(priv->mdev)) 4604 in_mdev = peer_priv->mdev; 4605 else 4606 in_mdev = priv->mdev; 4607 4608 parse_attr = flow->attr->parse_attr; 4609 peer_flow = __mlx5e_add_fdb_flow(peer_priv, f, flow_flags, 4610 parse_attr->filter_dev, 4611 attr->in_rep, in_mdev); 4612 if (IS_ERR(peer_flow)) { 4613 err = PTR_ERR(peer_flow); 4614 goto out; 4615 } 4616 4617 list_add_tail(&peer_flow->peer_flows, &flow->peer_flows); 4618 flow_flag_set(flow, DUP); 4619 mutex_lock(&esw->offloads.peer_mutex); 4620 list_add_tail(&flow->peer[i], &esw->offloads.peer_flows[i]); 4621 mutex_unlock(&esw->offloads.peer_mutex); 4622 4623out: 4624 return err; 4625} 4626 4627static int 4628mlx5e_add_fdb_flow(struct mlx5e_priv *priv, 4629 struct flow_cls_offload *f, 4630 unsigned long flow_flags, 4631 struct net_device *filter_dev, 4632 struct mlx5e_tc_flow **__flow) 4633{ 4634 struct mlx5_devcom_comp_dev *devcom = priv->mdev->priv.eswitch->devcom, *pos; 4635 struct mlx5e_rep_priv *rpriv = priv->ppriv; 4636 struct mlx5_eswitch_rep *in_rep = rpriv->rep; 4637 struct mlx5_core_dev *in_mdev = priv->mdev; 4638 struct mlx5_eswitch *peer_esw; 4639 struct mlx5e_tc_flow *flow; 4640 int err; 4641 4642 flow = __mlx5e_add_fdb_flow(priv, f, flow_flags, filter_dev, in_rep, 4643 in_mdev); 4644 if (IS_ERR(flow)) 4645 return PTR_ERR(flow); 4646 4647 if (!is_peer_flow_needed(flow)) { 4648 *__flow = flow; 4649 return 0; 4650 } 4651 4652 if (!mlx5_devcom_for_each_peer_begin(devcom)) { 4653 err = -ENODEV; 4654 goto clean_flow; 4655 } 4656 4657 mlx5_devcom_for_each_peer_entry(devcom, peer_esw, pos) { 4658 err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags, peer_esw); 4659 if (err) 4660 goto peer_clean; 4661 } 4662 4663 mlx5_devcom_for_each_peer_end(devcom); 4664 4665 *__flow = flow; 4666 return 0; 4667 4668peer_clean: 4669 mlx5e_tc_del_fdb_peers_flow(flow); 4670 mlx5_devcom_for_each_peer_end(devcom); 4671clean_flow: 4672 mlx5e_tc_del_fdb_flow(priv, flow); 4673 return err; 4674} 4675 4676static int 4677mlx5e_add_nic_flow(struct mlx5e_priv *priv, 4678 struct flow_cls_offload *f, 4679 unsigned long flow_flags, 4680 struct net_device *filter_dev, 4681 struct mlx5e_tc_flow **__flow) 4682{ 4683 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 4684 struct netlink_ext_ack *extack = f->common.extack; 4685 struct mlx5e_tc_flow_parse_attr *parse_attr; 4686 struct mlx5e_tc_flow *flow; 4687 int attr_size, err; 4688 4689 if (!MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, ignore_flow_level)) { 4690 if (!tc_cls_can_offload_and_chain0(priv->netdev, &f->common)) 4691 return -EOPNOTSUPP; 4692 } else if (!tc_can_offload_extack(priv->netdev, f->common.extack)) { 4693 return -EOPNOTSUPP; 4694 } 4695 4696 flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_NIC); 4697 attr_size = sizeof(struct mlx5_nic_flow_attr); 4698 err = mlx5e_alloc_flow(priv, attr_size, f, flow_flags, 4699 &parse_attr, &flow); 4700 if (err) 4701 goto out; 4702 4703 parse_attr->filter_dev = filter_dev; 4704 mlx5e_flow_attr_init(flow->attr, parse_attr, f); 4705 4706 err = parse_cls_flower(flow->priv, flow, &parse_attr->spec, 4707 f, filter_dev); 4708 if (err) 4709 goto err_free; 4710 4711 err = mlx5_tc_ct_match_add(get_ct_priv(priv), &parse_attr->spec, f, 4712 &flow->attr->ct_attr, extack); 4713 if (err) 4714 goto err_free; 4715 4716 err = parse_tc_nic_actions(priv, &rule->action, flow, extack); 4717 if (err) 4718 goto err_free; 4719 4720 err = mlx5e_tc_add_nic_flow(priv, flow, extack); 4721 if (err) 4722 goto err_free; 4723 4724 flow_flag_set(flow, OFFLOADED); 4725 *__flow = flow; 4726 4727 return 0; 4728 4729err_free: 4730 flow_flag_set(flow, FAILED); 4731 mlx5e_mod_hdr_dealloc(&parse_attr->mod_hdr_acts); 4732 mlx5e_flow_put(priv, flow); 4733out: 4734 return err; 4735} 4736 4737static int 4738mlx5e_tc_add_flow(struct mlx5e_priv *priv, 4739 struct flow_cls_offload *f, 4740 unsigned long flags, 4741 struct net_device *filter_dev, 4742 struct mlx5e_tc_flow **flow) 4743{ 4744 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 4745 unsigned long flow_flags; 4746 int err; 4747 4748 get_flags(flags, &flow_flags); 4749 4750 if (!tc_can_offload_extack(priv->netdev, f->common.extack)) 4751 return -EOPNOTSUPP; 4752 4753 if (esw && esw->mode == MLX5_ESWITCH_OFFLOADS) 4754 err = mlx5e_add_fdb_flow(priv, f, flow_flags, 4755 filter_dev, flow); 4756 else 4757 err = mlx5e_add_nic_flow(priv, f, flow_flags, 4758 filter_dev, flow); 4759 4760 return err; 4761} 4762 4763static bool is_flow_rule_duplicate_allowed(struct net_device *dev, 4764 struct mlx5e_rep_priv *rpriv) 4765{ 4766 /* Offloaded flow rule is allowed to duplicate on non-uplink representor 4767 * sharing tc block with other slaves of a lag device. Rpriv can be NULL if this 4768 * function is called from NIC mode. 4769 */ 4770 return netif_is_lag_port(dev) && rpriv && rpriv->rep->vport != MLX5_VPORT_UPLINK; 4771} 4772 4773/* As IPsec and TC order is not aligned between software and hardware-offload, 4774 * either IPsec offload or TC offload, not both, is allowed for a specific interface. 4775 */ 4776static bool is_tc_ipsec_order_check_needed(struct net_device *filter, struct mlx5e_priv *priv) 4777{ 4778 if (!IS_ENABLED(CONFIG_MLX5_EN_IPSEC)) 4779 return false; 4780 4781 if (filter != priv->netdev) 4782 return false; 4783 4784 if (mlx5e_eswitch_vf_rep(priv->netdev)) 4785 return false; 4786 4787 return true; 4788} 4789 4790static int mlx5e_tc_block_ipsec_offload(struct net_device *filter, struct mlx5e_priv *priv) 4791{ 4792 struct mlx5_core_dev *mdev = priv->mdev; 4793 4794 if (!is_tc_ipsec_order_check_needed(filter, priv)) 4795 return 0; 4796 4797 if (mdev->num_block_tc) 4798 return -EBUSY; 4799 4800 mdev->num_block_ipsec++; 4801 4802 return 0; 4803} 4804 4805static void mlx5e_tc_unblock_ipsec_offload(struct net_device *filter, struct mlx5e_priv *priv) 4806{ 4807 if (!is_tc_ipsec_order_check_needed(filter, priv)) 4808 return; 4809 4810 priv->mdev->num_block_ipsec--; 4811} 4812 4813int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv, 4814 struct flow_cls_offload *f, unsigned long flags) 4815{ 4816 struct netlink_ext_ack *extack = f->common.extack; 4817 struct rhashtable *tc_ht = get_tc_ht(priv, flags); 4818 struct mlx5e_rep_priv *rpriv = priv->ppriv; 4819 struct mlx5e_tc_flow *flow; 4820 int err = 0; 4821 4822 if (!mlx5_esw_hold(priv->mdev)) 4823 return -EBUSY; 4824 4825 err = mlx5e_tc_block_ipsec_offload(dev, priv); 4826 if (err) 4827 goto esw_release; 4828 4829 mlx5_esw_get(priv->mdev); 4830 4831 rcu_read_lock(); 4832 flow = rhashtable_lookup(tc_ht, &f->cookie, tc_ht_params); 4833 if (flow) { 4834 /* Same flow rule offloaded to non-uplink representor sharing tc block, 4835 * just return 0. 4836 */ 4837 if (is_flow_rule_duplicate_allowed(dev, rpriv) && flow->orig_dev != dev) 4838 goto rcu_unlock; 4839 4840 NL_SET_ERR_MSG_MOD(extack, 4841 "flow cookie already exists, ignoring"); 4842 netdev_warn_once(priv->netdev, 4843 "flow cookie %lx already exists, ignoring\n", 4844 f->cookie); 4845 err = -EEXIST; 4846 goto rcu_unlock; 4847 } 4848rcu_unlock: 4849 rcu_read_unlock(); 4850 if (flow) 4851 goto out; 4852 4853 trace_mlx5e_configure_flower(f); 4854 err = mlx5e_tc_add_flow(priv, f, flags, dev, &flow); 4855 if (err) 4856 goto out; 4857 4858 /* Flow rule offloaded to non-uplink representor sharing tc block, 4859 * set the flow's owner dev. 4860 */ 4861 if (is_flow_rule_duplicate_allowed(dev, rpriv)) 4862 flow->orig_dev = dev; 4863 4864 err = rhashtable_lookup_insert_fast(tc_ht, &flow->node, tc_ht_params); 4865 if (err) 4866 goto err_free; 4867 4868 mlx5_esw_release(priv->mdev); 4869 return 0; 4870 4871err_free: 4872 mlx5e_flow_put(priv, flow); 4873out: 4874 mlx5e_tc_unblock_ipsec_offload(dev, priv); 4875 mlx5_esw_put(priv->mdev); 4876esw_release: 4877 mlx5_esw_release(priv->mdev); 4878 return err; 4879} 4880 4881static bool same_flow_direction(struct mlx5e_tc_flow *flow, int flags) 4882{ 4883 bool dir_ingress = !!(flags & MLX5_TC_FLAG(INGRESS)); 4884 bool dir_egress = !!(flags & MLX5_TC_FLAG(EGRESS)); 4885 4886 return flow_flag_test(flow, INGRESS) == dir_ingress && 4887 flow_flag_test(flow, EGRESS) == dir_egress; 4888} 4889 4890int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv, 4891 struct flow_cls_offload *f, unsigned long flags) 4892{ 4893 struct rhashtable *tc_ht = get_tc_ht(priv, flags); 4894 struct mlx5e_tc_flow *flow; 4895 int err; 4896 4897 rcu_read_lock(); 4898 flow = rhashtable_lookup(tc_ht, &f->cookie, tc_ht_params); 4899 if (!flow || !same_flow_direction(flow, flags)) { 4900 err = -EINVAL; 4901 goto errout; 4902 } 4903 4904 /* Only delete the flow if it doesn't have MLX5E_TC_FLOW_DELETED flag 4905 * set. 4906 */ 4907 if (flow_flag_test_and_set(flow, DELETED)) { 4908 err = -EINVAL; 4909 goto errout; 4910 } 4911 rhashtable_remove_fast(tc_ht, &flow->node, tc_ht_params); 4912 rcu_read_unlock(); 4913 4914 trace_mlx5e_delete_flower(f); 4915 mlx5e_flow_put(priv, flow); 4916 4917 mlx5e_tc_unblock_ipsec_offload(dev, priv); 4918 mlx5_esw_put(priv->mdev); 4919 return 0; 4920 4921errout: 4922 rcu_read_unlock(); 4923 return err; 4924} 4925 4926int mlx5e_tc_fill_action_stats(struct mlx5e_priv *priv, 4927 struct flow_offload_action *fl_act) 4928{ 4929 return mlx5e_tc_act_stats_fill_stats(get_act_stats_handle(priv), fl_act); 4930} 4931 4932int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, 4933 struct flow_cls_offload *f, unsigned long flags) 4934{ 4935 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 4936 struct rhashtable *tc_ht = get_tc_ht(priv, flags); 4937 struct mlx5e_tc_flow *flow; 4938 struct mlx5_fc *counter; 4939 u64 lastuse = 0; 4940 u64 packets = 0; 4941 u64 bytes = 0; 4942 int err = 0; 4943 4944 rcu_read_lock(); 4945 flow = mlx5e_flow_get(rhashtable_lookup(tc_ht, &f->cookie, 4946 tc_ht_params)); 4947 rcu_read_unlock(); 4948 if (IS_ERR(flow)) 4949 return PTR_ERR(flow); 4950 4951 if (!same_flow_direction(flow, flags)) { 4952 err = -EINVAL; 4953 goto errout; 4954 } 4955 4956 if (mlx5e_is_offloaded_flow(flow)) { 4957 if (flow_flag_test(flow, USE_ACT_STATS)) { 4958 f->use_act_stats = true; 4959 } else { 4960 counter = mlx5e_tc_get_counter(flow); 4961 if (!counter) 4962 goto errout; 4963 4964 mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse); 4965 } 4966 } 4967 4968 /* Under multipath it's possible for one rule to be currently 4969 * un-offloaded while the other rule is offloaded. 4970 */ 4971 if (esw && !mlx5_devcom_for_each_peer_begin(esw->devcom)) 4972 goto out; 4973 4974 if (flow_flag_test(flow, DUP)) { 4975 struct mlx5e_tc_flow *peer_flow; 4976 4977 list_for_each_entry(peer_flow, &flow->peer_flows, peer_flows) { 4978 u64 packets2; 4979 u64 lastuse2; 4980 u64 bytes2; 4981 4982 if (!flow_flag_test(peer_flow, OFFLOADED)) 4983 continue; 4984 if (flow_flag_test(flow, USE_ACT_STATS)) { 4985 f->use_act_stats = true; 4986 break; 4987 } 4988 4989 counter = mlx5e_tc_get_counter(peer_flow); 4990 if (!counter) 4991 goto no_peer_counter; 4992 mlx5_fc_query_cached(counter, &bytes2, &packets2, 4993 &lastuse2); 4994 4995 bytes += bytes2; 4996 packets += packets2; 4997 lastuse = max_t(u64, lastuse, lastuse2); 4998 } 4999 } 5000 5001no_peer_counter: 5002 if (esw) 5003 mlx5_devcom_for_each_peer_end(esw->devcom); 5004out: 5005 flow_stats_update(&f->stats, bytes, packets, 0, lastuse, 5006 FLOW_ACTION_HW_STATS_DELAYED); 5007 trace_mlx5e_stats_flower(f); 5008errout: 5009 mlx5e_flow_put(priv, flow); 5010 return err; 5011} 5012 5013static int apply_police_params(struct mlx5e_priv *priv, u64 rate, 5014 struct netlink_ext_ack *extack) 5015{ 5016 struct mlx5e_rep_priv *rpriv = priv->ppriv; 5017 struct mlx5_eswitch *esw; 5018 u32 rate_mbps = 0; 5019 u16 vport_num; 5020 int err; 5021 5022 vport_num = rpriv->rep->vport; 5023 if (vport_num >= MLX5_VPORT_ECPF) { 5024 NL_SET_ERR_MSG_MOD(extack, 5025 "Ingress rate limit is supported only for Eswitch ports connected to VFs"); 5026 return -EOPNOTSUPP; 5027 } 5028 5029 esw = priv->mdev->priv.eswitch; 5030 /* rate is given in bytes/sec. 5031 * First convert to bits/sec and then round to the nearest mbit/secs. 5032 * mbit means million bits. 5033 * Moreover, if rate is non zero we choose to configure to a minimum of 5034 * 1 mbit/sec. 5035 */ 5036 if (rate) { 5037 rate = (rate * BITS_PER_BYTE) + 500000; 5038 do_div(rate, 1000000); 5039 rate_mbps = max_t(u32, rate, 1); 5040 } 5041 5042 err = mlx5_esw_qos_modify_vport_rate(esw, vport_num, rate_mbps); 5043 if (err) 5044 NL_SET_ERR_MSG_MOD(extack, "failed applying action to hardware"); 5045 5046 return err; 5047} 5048 5049static int 5050tc_matchall_police_validate(const struct flow_action *action, 5051 const struct flow_action_entry *act, 5052 struct netlink_ext_ack *extack) 5053{ 5054 if (act->police.notexceed.act_id != FLOW_ACTION_CONTINUE) { 5055 NL_SET_ERR_MSG_MOD(extack, 5056 "Offload not supported when conform action is not continue"); 5057 return -EOPNOTSUPP; 5058 } 5059 5060 if (act->police.exceed.act_id != FLOW_ACTION_DROP) { 5061 NL_SET_ERR_MSG_MOD(extack, 5062 "Offload not supported when exceed action is not drop"); 5063 return -EOPNOTSUPP; 5064 } 5065 5066 if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT && 5067 !flow_action_is_last_entry(action, act)) { 5068 NL_SET_ERR_MSG_MOD(extack, 5069 "Offload not supported when conform action is ok, but action is not last"); 5070 return -EOPNOTSUPP; 5071 } 5072 5073 if (act->police.peakrate_bytes_ps || 5074 act->police.avrate || act->police.overhead) { 5075 NL_SET_ERR_MSG_MOD(extack, 5076 "Offload not supported when peakrate/avrate/overhead is configured"); 5077 return -EOPNOTSUPP; 5078 } 5079 5080 return 0; 5081} 5082 5083static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv, 5084 struct flow_action *flow_action, 5085 struct netlink_ext_ack *extack) 5086{ 5087 struct mlx5e_rep_priv *rpriv = priv->ppriv; 5088 const struct flow_action_entry *act; 5089 int err; 5090 int i; 5091 5092 if (!flow_action_has_entries(flow_action)) { 5093 NL_SET_ERR_MSG_MOD(extack, "matchall called with no action"); 5094 return -EINVAL; 5095 } 5096 5097 if (!flow_offload_has_one_action(flow_action)) { 5098 NL_SET_ERR_MSG_MOD(extack, "matchall policing support only a single action"); 5099 return -EOPNOTSUPP; 5100 } 5101 5102 if (!flow_action_basic_hw_stats_check(flow_action, extack)) { 5103 NL_SET_ERR_MSG_MOD(extack, "Flow action HW stats type is not supported"); 5104 return -EOPNOTSUPP; 5105 } 5106 5107 flow_action_for_each(i, act, flow_action) { 5108 switch (act->id) { 5109 case FLOW_ACTION_POLICE: 5110 err = tc_matchall_police_validate(flow_action, act, extack); 5111 if (err) 5112 return err; 5113 5114 err = apply_police_params(priv, act->police.rate_bytes_ps, extack); 5115 if (err) 5116 return err; 5117 5118 mlx5e_stats_copy_rep_stats(&rpriv->prev_vf_vport_stats, 5119 &priv->stats.rep_stats); 5120 break; 5121 default: 5122 NL_SET_ERR_MSG_MOD(extack, "mlx5 supports only police action for matchall"); 5123 return -EOPNOTSUPP; 5124 } 5125 } 5126 5127 return 0; 5128} 5129 5130int mlx5e_tc_configure_matchall(struct mlx5e_priv *priv, 5131 struct tc_cls_matchall_offload *ma) 5132{ 5133 struct netlink_ext_ack *extack = ma->common.extack; 5134 5135 if (ma->common.prio != 1) { 5136 NL_SET_ERR_MSG_MOD(extack, "only priority 1 is supported"); 5137 return -EINVAL; 5138 } 5139 5140 return scan_tc_matchall_fdb_actions(priv, &ma->rule->action, extack); 5141} 5142 5143int mlx5e_tc_delete_matchall(struct mlx5e_priv *priv, 5144 struct tc_cls_matchall_offload *ma) 5145{ 5146 struct netlink_ext_ack *extack = ma->common.extack; 5147 5148 return apply_police_params(priv, 0, extack); 5149} 5150 5151static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv, 5152 struct mlx5e_priv *peer_priv) 5153{ 5154 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 5155 struct mlx5_core_dev *peer_mdev = peer_priv->mdev; 5156 struct mlx5e_hairpin_entry *hpe, *tmp; 5157 LIST_HEAD(init_wait_list); 5158 u16 peer_vhca_id; 5159 int bkt; 5160 5161 if (!mlx5e_same_hw_devs(priv, peer_priv)) 5162 return; 5163 5164 peer_vhca_id = MLX5_CAP_GEN(peer_mdev, vhca_id); 5165 5166 mutex_lock(&tc->hairpin_tbl_lock); 5167 hash_for_each(tc->hairpin_tbl, bkt, hpe, hairpin_hlist) 5168 if (refcount_inc_not_zero(&hpe->refcnt)) 5169 list_add(&hpe->dead_peer_wait_list, &init_wait_list); 5170 mutex_unlock(&tc->hairpin_tbl_lock); 5171 5172 list_for_each_entry_safe(hpe, tmp, &init_wait_list, dead_peer_wait_list) { 5173 wait_for_completion(&hpe->res_ready); 5174 if (!IS_ERR_OR_NULL(hpe->hp) && hpe->peer_vhca_id == peer_vhca_id) 5175 mlx5_core_hairpin_clear_dead_peer(hpe->hp->pair); 5176 5177 mlx5e_hairpin_put(priv, hpe); 5178 } 5179} 5180 5181static int mlx5e_tc_netdev_event(struct notifier_block *this, 5182 unsigned long event, void *ptr) 5183{ 5184 struct net_device *ndev = netdev_notifier_info_to_dev(ptr); 5185 struct mlx5e_priv *peer_priv; 5186 struct mlx5e_tc_table *tc; 5187 struct mlx5e_priv *priv; 5188 5189 if (ndev->netdev_ops != &mlx5e_netdev_ops || 5190 event != NETDEV_UNREGISTER || 5191 ndev->reg_state == NETREG_REGISTERED) 5192 return NOTIFY_DONE; 5193 5194 tc = container_of(this, struct mlx5e_tc_table, netdevice_nb); 5195 priv = tc->priv; 5196 peer_priv = netdev_priv(ndev); 5197 if (priv == peer_priv || 5198 !(priv->netdev->features & NETIF_F_HW_TC)) 5199 return NOTIFY_DONE; 5200 5201 mlx5e_tc_hairpin_update_dead_peer(priv, peer_priv); 5202 5203 return NOTIFY_DONE; 5204} 5205 5206static int mlx5e_tc_nic_create_miss_table(struct mlx5e_priv *priv) 5207{ 5208 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 5209 struct mlx5_flow_table **ft = &tc->miss_t; 5210 struct mlx5_flow_table_attr ft_attr = {}; 5211 struct mlx5_flow_namespace *ns; 5212 int err = 0; 5213 5214 ft_attr.max_fte = 1; 5215 ft_attr.autogroup.max_num_groups = 1; 5216 ft_attr.level = MLX5E_TC_MISS_LEVEL; 5217 ft_attr.prio = 0; 5218 ns = mlx5_get_flow_namespace(priv->mdev, MLX5_FLOW_NAMESPACE_KERNEL); 5219 5220 *ft = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); 5221 if (IS_ERR(*ft)) { 5222 err = PTR_ERR(*ft); 5223 netdev_err(priv->netdev, "failed to create tc nic miss table err=%d\n", err); 5224 } 5225 5226 return err; 5227} 5228 5229static void mlx5e_tc_nic_destroy_miss_table(struct mlx5e_priv *priv) 5230{ 5231 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 5232 5233 mlx5_destroy_flow_table(tc->miss_t); 5234} 5235 5236int mlx5e_tc_nic_init(struct mlx5e_priv *priv) 5237{ 5238 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 5239 u8 mapping_id[MLX5_SW_IMAGE_GUID_MAX_BYTES]; 5240 struct mlx5_core_dev *dev = priv->mdev; 5241 struct mapping_ctx *chains_mapping; 5242 struct mlx5_chains_attr attr = {}; 5243 u8 id_len; 5244 int err; 5245 5246 mlx5e_mod_hdr_tbl_init(&tc->mod_hdr); 5247 mutex_init(&tc->t_lock); 5248 mutex_init(&tc->hairpin_tbl_lock); 5249 hash_init(tc->hairpin_tbl); 5250 tc->priv = priv; 5251 5252 err = rhashtable_init(&tc->ht, &tc_ht_params); 5253 if (err) 5254 return err; 5255 5256 lockdep_set_class(&tc->ht.mutex, &tc_ht_lock_key); 5257 lockdep_init_map(&tc->ht.run_work.lockdep_map, "tc_ht_wq_key", &tc_ht_wq_key, 0); 5258 5259 mlx5_query_nic_sw_system_image_guid(dev, mapping_id, &id_len); 5260 5261 chains_mapping = mapping_create_for_id(mapping_id, id_len, 5262 MAPPING_TYPE_CHAIN, 5263 sizeof(struct mlx5_mapped_obj), 5264 MLX5E_TC_TABLE_CHAIN_TAG_MASK, 5265 true); 5266 5267 if (IS_ERR(chains_mapping)) { 5268 err = PTR_ERR(chains_mapping); 5269 goto err_mapping; 5270 } 5271 tc->mapping = chains_mapping; 5272 5273 err = mlx5e_tc_nic_create_miss_table(priv); 5274 if (err) 5275 goto err_chains; 5276 5277 if (MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, ignore_flow_level)) 5278 attr.flags = MLX5_CHAINS_AND_PRIOS_SUPPORTED | 5279 MLX5_CHAINS_IGNORE_FLOW_LEVEL_SUPPORTED; 5280 attr.ns = MLX5_FLOW_NAMESPACE_KERNEL; 5281 attr.max_grp_num = MLX5E_TC_TABLE_NUM_GROUPS; 5282 attr.default_ft = tc->miss_t; 5283 attr.mapping = chains_mapping; 5284 attr.fs_base_prio = MLX5E_TC_PRIO; 5285 5286 tc->chains = mlx5_chains_create(dev, &attr); 5287 if (IS_ERR(tc->chains)) { 5288 err = PTR_ERR(tc->chains); 5289 goto err_miss; 5290 } 5291 5292 mlx5_chains_print_info(tc->chains); 5293 5294 tc->post_act = mlx5e_tc_post_act_init(priv, tc->chains, MLX5_FLOW_NAMESPACE_KERNEL); 5295 tc->ct = mlx5_tc_ct_init(priv, tc->chains, &tc->mod_hdr, 5296 MLX5_FLOW_NAMESPACE_KERNEL, tc->post_act); 5297 5298 tc->netdevice_nb.notifier_call = mlx5e_tc_netdev_event; 5299 err = register_netdevice_notifier_dev_net(priv->netdev, 5300 &tc->netdevice_nb, 5301 &tc->netdevice_nn); 5302 if (err) { 5303 tc->netdevice_nb.notifier_call = NULL; 5304 mlx5_core_warn(priv->mdev, "Failed to register netdev notifier\n"); 5305 goto err_reg; 5306 } 5307 5308 mlx5e_tc_debugfs_init(tc, mlx5e_fs_get_debugfs_root(priv->fs)); 5309 5310 tc->action_stats_handle = mlx5e_tc_act_stats_create(); 5311 if (IS_ERR(tc->action_stats_handle)) { 5312 err = PTR_ERR(tc->action_stats_handle); 5313 goto err_act_stats; 5314 } 5315 5316 return 0; 5317 5318err_act_stats: 5319 unregister_netdevice_notifier_dev_net(priv->netdev, 5320 &tc->netdevice_nb, 5321 &tc->netdevice_nn); 5322err_reg: 5323 mlx5_tc_ct_clean(tc->ct); 5324 mlx5e_tc_post_act_destroy(tc->post_act); 5325 mlx5_chains_destroy(tc->chains); 5326err_miss: 5327 mlx5e_tc_nic_destroy_miss_table(priv); 5328err_chains: 5329 mapping_destroy(chains_mapping); 5330err_mapping: 5331 rhashtable_destroy(&tc->ht); 5332 return err; 5333} 5334 5335static void _mlx5e_tc_del_flow(void *ptr, void *arg) 5336{ 5337 struct mlx5e_tc_flow *flow = ptr; 5338 struct mlx5e_priv *priv = flow->priv; 5339 5340 mlx5e_tc_del_flow(priv, flow); 5341 kfree(flow); 5342} 5343 5344void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv) 5345{ 5346 struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs); 5347 5348 debugfs_remove_recursive(tc->dfs_root); 5349 5350 if (tc->netdevice_nb.notifier_call) 5351 unregister_netdevice_notifier_dev_net(priv->netdev, 5352 &tc->netdevice_nb, 5353 &tc->netdevice_nn); 5354 5355 mlx5e_mod_hdr_tbl_destroy(&tc->mod_hdr); 5356 mutex_destroy(&tc->hairpin_tbl_lock); 5357 5358 rhashtable_free_and_destroy(&tc->ht, _mlx5e_tc_del_flow, NULL); 5359 5360 if (!IS_ERR_OR_NULL(tc->t)) { 5361 mlx5_chains_put_table(tc->chains, 0, 1, MLX5E_TC_FT_LEVEL); 5362 tc->t = NULL; 5363 } 5364 mutex_destroy(&tc->t_lock); 5365 5366 mlx5_tc_ct_clean(tc->ct); 5367 mlx5e_tc_post_act_destroy(tc->post_act); 5368 mapping_destroy(tc->mapping); 5369 mlx5_chains_destroy(tc->chains); 5370 mlx5e_tc_nic_destroy_miss_table(priv); 5371 mlx5e_tc_act_stats_free(tc->action_stats_handle); 5372} 5373 5374int mlx5e_tc_ht_init(struct rhashtable *tc_ht) 5375{ 5376 int err; 5377 5378 err = rhashtable_init(tc_ht, &tc_ht_params); 5379 if (err) 5380 return err; 5381 5382 lockdep_set_class(&tc_ht->mutex, &tc_ht_lock_key); 5383 lockdep_init_map(&tc_ht->run_work.lockdep_map, "tc_ht_wq_key", &tc_ht_wq_key, 0); 5384 5385 return 0; 5386} 5387 5388void mlx5e_tc_ht_cleanup(struct rhashtable *tc_ht) 5389{ 5390 rhashtable_free_and_destroy(tc_ht, _mlx5e_tc_del_flow, NULL); 5391} 5392 5393int mlx5e_tc_esw_init(struct mlx5_rep_uplink_priv *uplink_priv) 5394{ 5395 const size_t sz_enc_opts = sizeof(struct tunnel_match_enc_opts); 5396 u8 mapping_id[MLX5_SW_IMAGE_GUID_MAX_BYTES]; 5397 struct mlx5_devcom_match_attr attr = {}; 5398 struct netdev_phys_item_id ppid; 5399 struct mlx5e_rep_priv *rpriv; 5400 struct mapping_ctx *mapping; 5401 struct mlx5_eswitch *esw; 5402 struct mlx5e_priv *priv; 5403 int err = 0; 5404 u8 id_len; 5405 5406 rpriv = container_of(uplink_priv, struct mlx5e_rep_priv, uplink_priv); 5407 priv = netdev_priv(rpriv->netdev); 5408 esw = priv->mdev->priv.eswitch; 5409 5410 uplink_priv->post_act = mlx5e_tc_post_act_init(priv, esw_chains(esw), 5411 MLX5_FLOW_NAMESPACE_FDB); 5412 uplink_priv->ct_priv = mlx5_tc_ct_init(netdev_priv(priv->netdev), 5413 esw_chains(esw), 5414 &esw->offloads.mod_hdr, 5415 MLX5_FLOW_NAMESPACE_FDB, 5416 uplink_priv->post_act); 5417 5418 uplink_priv->int_port_priv = mlx5e_tc_int_port_init(netdev_priv(priv->netdev)); 5419 5420 uplink_priv->tc_psample = mlx5e_tc_sample_init(esw, uplink_priv->post_act); 5421 5422 mlx5_query_nic_sw_system_image_guid(esw->dev, mapping_id, &id_len); 5423 5424 mapping = mapping_create_for_id(mapping_id, id_len, MAPPING_TYPE_TUNNEL, 5425 sizeof(struct tunnel_match_key), 5426 TUNNEL_INFO_BITS_MASK, true); 5427 5428 if (IS_ERR(mapping)) { 5429 err = PTR_ERR(mapping); 5430 goto err_tun_mapping; 5431 } 5432 uplink_priv->tunnel_mapping = mapping; 5433 5434 /* Two last values are reserved for stack devices slow path table mark 5435 * and bridge ingress push mark. 5436 */ 5437 mapping = mapping_create_for_id(mapping_id, id_len, 5438 MAPPING_TYPE_TUNNEL_ENC_OPTS, 5439 sz_enc_opts, ENC_OPTS_BITS_MASK - 2, 5440 true); 5441 if (IS_ERR(mapping)) { 5442 err = PTR_ERR(mapping); 5443 goto err_enc_opts_mapping; 5444 } 5445 uplink_priv->tunnel_enc_opts_mapping = mapping; 5446 5447 uplink_priv->encap = mlx5e_tc_tun_init(priv); 5448 if (IS_ERR(uplink_priv->encap)) { 5449 err = PTR_ERR(uplink_priv->encap); 5450 goto err_register_fib_notifier; 5451 } 5452 5453 uplink_priv->action_stats_handle = mlx5e_tc_act_stats_create(); 5454 if (IS_ERR(uplink_priv->action_stats_handle)) { 5455 err = PTR_ERR(uplink_priv->action_stats_handle); 5456 goto err_action_counter; 5457 } 5458 5459 err = netif_get_port_parent_id(priv->netdev, &ppid, false); 5460 if (!err) { 5461 memcpy(&attr.key.buf, &ppid.id, ppid.id_len); 5462 attr.flags = MLX5_DEVCOM_MATCH_FLAGS_NS; 5463 attr.net = mlx5_core_net(esw->dev); 5464 mlx5_esw_offloads_devcom_init(esw, &attr); 5465 } 5466 5467 return 0; 5468 5469err_action_counter: 5470 mlx5e_tc_tun_cleanup(uplink_priv->encap); 5471err_register_fib_notifier: 5472 mapping_destroy(uplink_priv->tunnel_enc_opts_mapping); 5473err_enc_opts_mapping: 5474 mapping_destroy(uplink_priv->tunnel_mapping); 5475err_tun_mapping: 5476 mlx5e_tc_sample_cleanup(uplink_priv->tc_psample); 5477 mlx5e_tc_int_port_cleanup(uplink_priv->int_port_priv); 5478 mlx5_tc_ct_clean(uplink_priv->ct_priv); 5479 netdev_warn(priv->netdev, 5480 "Failed to initialize tc (eswitch), err: %d", err); 5481 mlx5e_tc_post_act_destroy(uplink_priv->post_act); 5482 return err; 5483} 5484 5485void mlx5e_tc_esw_cleanup(struct mlx5_rep_uplink_priv *uplink_priv) 5486{ 5487 struct mlx5e_rep_priv *rpriv; 5488 struct mlx5_eswitch *esw; 5489 struct mlx5e_priv *priv; 5490 5491 rpriv = container_of(uplink_priv, struct mlx5e_rep_priv, uplink_priv); 5492 priv = netdev_priv(rpriv->netdev); 5493 esw = priv->mdev->priv.eswitch; 5494 5495 mlx5_esw_offloads_devcom_cleanup(esw); 5496 5497 mlx5e_tc_tun_cleanup(uplink_priv->encap); 5498 5499 mapping_destroy(uplink_priv->tunnel_enc_opts_mapping); 5500 mapping_destroy(uplink_priv->tunnel_mapping); 5501 5502 mlx5e_tc_sample_cleanup(uplink_priv->tc_psample); 5503 mlx5e_tc_int_port_cleanup(uplink_priv->int_port_priv); 5504 mlx5_tc_ct_clean(uplink_priv->ct_priv); 5505 mlx5e_flow_meters_cleanup(uplink_priv->flow_meters); 5506 mlx5e_tc_post_act_destroy(uplink_priv->post_act); 5507 mlx5e_tc_act_stats_free(uplink_priv->action_stats_handle); 5508} 5509 5510int mlx5e_tc_num_filters(struct mlx5e_priv *priv, unsigned long flags) 5511{ 5512 struct rhashtable *tc_ht = get_tc_ht(priv, flags); 5513 5514 return atomic_read(&tc_ht->nelems); 5515} 5516 5517void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw) 5518{ 5519 struct mlx5_devcom_comp_dev *devcom; 5520 struct mlx5_devcom_comp_dev *pos; 5521 struct mlx5e_tc_flow *flow, *tmp; 5522 struct mlx5_eswitch *peer_esw; 5523 int i; 5524 5525 devcom = esw->devcom; 5526 5527 mlx5_devcom_for_each_peer_entry(devcom, peer_esw, pos) { 5528 i = mlx5_get_dev_index(peer_esw->dev); 5529 list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows[i], peer[i]) 5530 mlx5e_tc_del_fdb_peers_flow(flow); 5531 } 5532} 5533 5534void mlx5e_tc_reoffload_flows_work(struct work_struct *work) 5535{ 5536 struct mlx5_rep_uplink_priv *rpriv = 5537 container_of(work, struct mlx5_rep_uplink_priv, 5538 reoffload_flows_work); 5539 struct mlx5e_tc_flow *flow, *tmp; 5540 5541 mutex_lock(&rpriv->unready_flows_lock); 5542 list_for_each_entry_safe(flow, tmp, &rpriv->unready_flows, unready) { 5543 if (!mlx5e_tc_add_fdb_flow(flow->priv, flow, NULL)) 5544 unready_flow_del(flow); 5545 } 5546 mutex_unlock(&rpriv->unready_flows_lock); 5547} 5548 5549static int mlx5e_setup_tc_cls_flower(struct mlx5e_priv *priv, 5550 struct flow_cls_offload *cls_flower, 5551 unsigned long flags) 5552{ 5553 switch (cls_flower->command) { 5554 case FLOW_CLS_REPLACE: 5555 return mlx5e_configure_flower(priv->netdev, priv, cls_flower, 5556 flags); 5557 case FLOW_CLS_DESTROY: 5558 return mlx5e_delete_flower(priv->netdev, priv, cls_flower, 5559 flags); 5560 case FLOW_CLS_STATS: 5561 return mlx5e_stats_flower(priv->netdev, priv, cls_flower, 5562 flags); 5563 default: 5564 return -EOPNOTSUPP; 5565 } 5566} 5567 5568int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data, 5569 void *cb_priv) 5570{ 5571 unsigned long flags = MLX5_TC_FLAG(INGRESS); 5572 struct mlx5e_priv *priv = cb_priv; 5573 5574 if (!priv->netdev || !netif_device_present(priv->netdev)) 5575 return -EOPNOTSUPP; 5576 5577 if (mlx5e_is_uplink_rep(priv)) 5578 flags |= MLX5_TC_FLAG(ESW_OFFLOAD); 5579 else 5580 flags |= MLX5_TC_FLAG(NIC_OFFLOAD); 5581 5582 switch (type) { 5583 case TC_SETUP_CLSFLOWER: 5584 return mlx5e_setup_tc_cls_flower(priv, type_data, flags); 5585 default: 5586 return -EOPNOTSUPP; 5587 } 5588} 5589 5590static bool mlx5e_tc_restore_tunnel(struct mlx5e_priv *priv, struct sk_buff *skb, 5591 struct mlx5e_tc_update_priv *tc_priv, 5592 u32 tunnel_id) 5593{ 5594 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 5595 struct tunnel_match_enc_opts enc_opts = {}; 5596 struct mlx5_rep_uplink_priv *uplink_priv; 5597 IP_TUNNEL_DECLARE_FLAGS(flags) = { }; 5598 struct mlx5e_rep_priv *uplink_rpriv; 5599 struct metadata_dst *tun_dst; 5600 struct tunnel_match_key key; 5601 u32 tun_id, enc_opts_id; 5602 struct net_device *dev; 5603 int err; 5604 5605 __set_bit(IP_TUNNEL_KEY_BIT, flags); 5606 5607 enc_opts_id = tunnel_id & ENC_OPTS_BITS_MASK; 5608 tun_id = tunnel_id >> ENC_OPTS_BITS; 5609 5610 if (!tun_id) 5611 return true; 5612 5613 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 5614 uplink_priv = &uplink_rpriv->uplink_priv; 5615 5616 err = mapping_find(uplink_priv->tunnel_mapping, tun_id, &key); 5617 if (err) { 5618 netdev_dbg(priv->netdev, 5619 "Couldn't find tunnel for tun_id: %d, err: %d\n", 5620 tun_id, err); 5621 return false; 5622 } 5623 5624 if (enc_opts_id) { 5625 err = mapping_find(uplink_priv->tunnel_enc_opts_mapping, 5626 enc_opts_id, &enc_opts); 5627 if (err) { 5628 netdev_dbg(priv->netdev, 5629 "Couldn't find tunnel (opts) for tun_id: %d, err: %d\n", 5630 enc_opts_id, err); 5631 return false; 5632 } 5633 } 5634 5635 switch (key.enc_control.addr_type) { 5636 case FLOW_DISSECTOR_KEY_IPV4_ADDRS: 5637 tun_dst = __ip_tun_set_dst(key.enc_ipv4.src, key.enc_ipv4.dst, 5638 key.enc_ip.tos, key.enc_ip.ttl, 5639 key.enc_tp.dst, flags, 5640 key32_to_tunnel_id(key.enc_key_id.keyid), 5641 enc_opts.key.len); 5642 break; 5643 case FLOW_DISSECTOR_KEY_IPV6_ADDRS: 5644 tun_dst = __ipv6_tun_set_dst(&key.enc_ipv6.src, &key.enc_ipv6.dst, 5645 key.enc_ip.tos, key.enc_ip.ttl, 5646 key.enc_tp.dst, 0, flags, 5647 key32_to_tunnel_id(key.enc_key_id.keyid), 5648 enc_opts.key.len); 5649 break; 5650 default: 5651 netdev_dbg(priv->netdev, 5652 "Couldn't restore tunnel, unsupported addr_type: %d\n", 5653 key.enc_control.addr_type); 5654 return false; 5655 } 5656 5657 if (!tun_dst) { 5658 netdev_dbg(priv->netdev, "Couldn't restore tunnel, no tun_dst\n"); 5659 return false; 5660 } 5661 5662 tun_dst->u.tun_info.key.tp_src = key.enc_tp.src; 5663 5664 if (enc_opts.key.len) { 5665 ip_tunnel_flags_zero(flags); 5666 if (enc_opts.key.dst_opt_type) 5667 __set_bit(enc_opts.key.dst_opt_type, flags); 5668 5669 ip_tunnel_info_opts_set(&tun_dst->u.tun_info, 5670 enc_opts.key.data, 5671 enc_opts.key.len, 5672 flags); 5673 } 5674 5675 skb_dst_set(skb, (struct dst_entry *)tun_dst); 5676 dev = dev_get_by_index(&init_net, key.filter_ifindex); 5677 if (!dev) { 5678 netdev_dbg(priv->netdev, 5679 "Couldn't find tunnel device with ifindex: %d\n", 5680 key.filter_ifindex); 5681 return false; 5682 } 5683 5684 /* Set fwd_dev so we do dev_put() after datapath */ 5685 tc_priv->fwd_dev = dev; 5686 5687 skb->dev = dev; 5688 5689 return true; 5690} 5691 5692static bool mlx5e_tc_restore_skb_tc_meta(struct sk_buff *skb, struct mlx5_tc_ct_priv *ct_priv, 5693 struct mlx5_mapped_obj *mapped_obj, u32 zone_restore_id, 5694 u32 tunnel_id, struct mlx5e_tc_update_priv *tc_priv) 5695{ 5696 struct mlx5e_priv *priv = netdev_priv(skb->dev); 5697 struct tc_skb_ext *tc_skb_ext; 5698 u64 act_miss_cookie; 5699 u32 chain; 5700 5701 chain = mapped_obj->type == MLX5_MAPPED_OBJ_CHAIN ? mapped_obj->chain : 0; 5702 act_miss_cookie = mapped_obj->type == MLX5_MAPPED_OBJ_ACT_MISS ? 5703 mapped_obj->act_miss_cookie : 0; 5704 if (chain || act_miss_cookie) { 5705 if (!mlx5e_tc_ct_restore_flow(ct_priv, skb, zone_restore_id)) 5706 return false; 5707 5708 tc_skb_ext = tc_skb_ext_alloc(skb); 5709 if (!tc_skb_ext) { 5710 WARN_ON(1); 5711 return false; 5712 } 5713 5714 if (act_miss_cookie) { 5715 tc_skb_ext->act_miss_cookie = act_miss_cookie; 5716 tc_skb_ext->act_miss = 1; 5717 } else { 5718 tc_skb_ext->chain = chain; 5719 } 5720 } 5721 5722 if (tc_priv) 5723 return mlx5e_tc_restore_tunnel(priv, skb, tc_priv, tunnel_id); 5724 5725 return true; 5726} 5727 5728static void mlx5e_tc_restore_skb_sample(struct mlx5e_priv *priv, struct sk_buff *skb, 5729 struct mlx5_mapped_obj *mapped_obj, 5730 struct mlx5e_tc_update_priv *tc_priv) 5731{ 5732 if (!mlx5e_tc_restore_tunnel(priv, skb, tc_priv, mapped_obj->sample.tunnel_id)) { 5733 netdev_dbg(priv->netdev, 5734 "Failed to restore tunnel info for sampled packet\n"); 5735 return; 5736 } 5737 mlx5e_tc_sample_skb(skb, mapped_obj); 5738} 5739 5740static bool mlx5e_tc_restore_skb_int_port(struct mlx5e_priv *priv, struct sk_buff *skb, 5741 struct mlx5_mapped_obj *mapped_obj, 5742 struct mlx5e_tc_update_priv *tc_priv, 5743 u32 tunnel_id) 5744{ 5745 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 5746 struct mlx5_rep_uplink_priv *uplink_priv; 5747 struct mlx5e_rep_priv *uplink_rpriv; 5748 bool forward_tx = false; 5749 5750 /* Tunnel restore takes precedence over int port restore */ 5751 if (tunnel_id) 5752 return mlx5e_tc_restore_tunnel(priv, skb, tc_priv, tunnel_id); 5753 5754 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 5755 uplink_priv = &uplink_rpriv->uplink_priv; 5756 5757 if (mlx5e_tc_int_port_dev_fwd(uplink_priv->int_port_priv, skb, 5758 mapped_obj->int_port_metadata, &forward_tx)) { 5759 /* Set fwd_dev for future dev_put */ 5760 tc_priv->fwd_dev = skb->dev; 5761 tc_priv->forward_tx = forward_tx; 5762 5763 return true; 5764 } 5765 5766 return false; 5767} 5768 5769bool mlx5e_tc_update_skb(struct mlx5_cqe64 *cqe, struct sk_buff *skb, 5770 struct mapping_ctx *mapping_ctx, u32 mapped_obj_id, 5771 struct mlx5_tc_ct_priv *ct_priv, 5772 u32 zone_restore_id, u32 tunnel_id, 5773 struct mlx5e_tc_update_priv *tc_priv) 5774{ 5775 struct mlx5e_priv *priv = netdev_priv(skb->dev); 5776 struct mlx5_mapped_obj mapped_obj; 5777 int err; 5778 5779 err = mapping_find(mapping_ctx, mapped_obj_id, &mapped_obj); 5780 if (err) { 5781 netdev_dbg(skb->dev, 5782 "Couldn't find mapped object for mapped_obj_id: %d, err: %d\n", 5783 mapped_obj_id, err); 5784 return false; 5785 } 5786 5787 switch (mapped_obj.type) { 5788 case MLX5_MAPPED_OBJ_CHAIN: 5789 case MLX5_MAPPED_OBJ_ACT_MISS: 5790 return mlx5e_tc_restore_skb_tc_meta(skb, ct_priv, &mapped_obj, zone_restore_id, 5791 tunnel_id, tc_priv); 5792 case MLX5_MAPPED_OBJ_SAMPLE: 5793 mlx5e_tc_restore_skb_sample(priv, skb, &mapped_obj, tc_priv); 5794 tc_priv->skb_done = true; 5795 return true; 5796 case MLX5_MAPPED_OBJ_INT_PORT_METADATA: 5797 return mlx5e_tc_restore_skb_int_port(priv, skb, &mapped_obj, tc_priv, tunnel_id); 5798 default: 5799 netdev_dbg(priv->netdev, "Invalid mapped object type: %d\n", mapped_obj.type); 5800 return false; 5801 } 5802 5803 return false; 5804} 5805 5806bool mlx5e_tc_update_skb_nic(struct mlx5_cqe64 *cqe, struct sk_buff *skb) 5807{ 5808 struct mlx5e_priv *priv = netdev_priv(skb->dev); 5809 u32 mapped_obj_id, reg_b, zone_restore_id; 5810 struct mlx5_tc_ct_priv *ct_priv; 5811 struct mapping_ctx *mapping_ctx; 5812 struct mlx5e_tc_table *tc; 5813 5814 reg_b = be32_to_cpu(cqe->ft_metadata); 5815 tc = mlx5e_fs_get_tc(priv->fs); 5816 mapped_obj_id = reg_b & MLX5E_TC_TABLE_CHAIN_TAG_MASK; 5817 zone_restore_id = (reg_b >> MLX5_REG_MAPPING_MOFFSET(NIC_ZONE_RESTORE_TO_REG)) & 5818 ESW_ZONE_ID_MASK; 5819 ct_priv = tc->ct; 5820 mapping_ctx = tc->mapping; 5821 5822 return mlx5e_tc_update_skb(cqe, skb, mapping_ctx, mapped_obj_id, ct_priv, zone_restore_id, 5823 0, NULL); 5824} 5825 5826static struct mapping_ctx * 5827mlx5e_get_priv_obj_mapping(struct mlx5e_priv *priv) 5828{ 5829 struct mlx5e_tc_table *tc; 5830 struct mlx5_eswitch *esw; 5831 struct mapping_ctx *ctx; 5832 5833 if (is_mdev_switchdev_mode(priv->mdev)) { 5834 esw = priv->mdev->priv.eswitch; 5835 ctx = esw->offloads.reg_c0_obj_pool; 5836 } else { 5837 tc = mlx5e_fs_get_tc(priv->fs); 5838 ctx = tc->mapping; 5839 } 5840 5841 return ctx; 5842} 5843 5844int mlx5e_tc_action_miss_mapping_get(struct mlx5e_priv *priv, struct mlx5_flow_attr *attr, 5845 u64 act_miss_cookie, u32 *act_miss_mapping) 5846{ 5847 struct mlx5_mapped_obj mapped_obj = {}; 5848 struct mlx5_eswitch *esw; 5849 struct mapping_ctx *ctx; 5850 int err; 5851 5852 ctx = mlx5e_get_priv_obj_mapping(priv); 5853 mapped_obj.type = MLX5_MAPPED_OBJ_ACT_MISS; 5854 mapped_obj.act_miss_cookie = act_miss_cookie; 5855 err = mapping_add(ctx, &mapped_obj, act_miss_mapping); 5856 if (err) 5857 return err; 5858 5859 if (!is_mdev_switchdev_mode(priv->mdev)) 5860 return 0; 5861 5862 esw = priv->mdev->priv.eswitch; 5863 attr->act_id_restore_rule = esw_add_restore_rule(esw, *act_miss_mapping); 5864 if (IS_ERR(attr->act_id_restore_rule)) { 5865 err = PTR_ERR(attr->act_id_restore_rule); 5866 goto err_rule; 5867 } 5868 5869 return 0; 5870 5871err_rule: 5872 mapping_remove(ctx, *act_miss_mapping); 5873 return err; 5874} 5875 5876void mlx5e_tc_action_miss_mapping_put(struct mlx5e_priv *priv, struct mlx5_flow_attr *attr, 5877 u32 act_miss_mapping) 5878{ 5879 struct mapping_ctx *ctx = mlx5e_get_priv_obj_mapping(priv); 5880 5881 if (is_mdev_switchdev_mode(priv->mdev)) 5882 mlx5_del_flow_rules(attr->act_id_restore_rule); 5883 mapping_remove(ctx, act_miss_mapping); 5884}
~/
Read-only file preview.