19db810edSAlex Vesker // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 29db810edSAlex Vesker /* Copyright (c) 2019 Mellanox Technologies. */ 39db810edSAlex Vesker 49db810edSAlex Vesker #include "dr_types.h" 59db810edSAlex Vesker 69db810edSAlex Vesker enum dr_action_domain { 79db810edSAlex Vesker DR_ACTION_DOMAIN_NIC_INGRESS, 89db810edSAlex Vesker DR_ACTION_DOMAIN_NIC_EGRESS, 99db810edSAlex Vesker DR_ACTION_DOMAIN_FDB_INGRESS, 109db810edSAlex Vesker DR_ACTION_DOMAIN_FDB_EGRESS, 119db810edSAlex Vesker DR_ACTION_DOMAIN_MAX, 129db810edSAlex Vesker }; 139db810edSAlex Vesker 149db810edSAlex Vesker enum dr_action_valid_state { 159db810edSAlex Vesker DR_ACTION_STATE_ERR, 169db810edSAlex Vesker DR_ACTION_STATE_NO_ACTION, 17*28de41a4SYevgeny Kliteynik DR_ACTION_STATE_ENCAP, 18*28de41a4SYevgeny Kliteynik DR_ACTION_STATE_DECAP, 199db810edSAlex Vesker DR_ACTION_STATE_MODIFY_HDR, 209db810edSAlex Vesker DR_ACTION_STATE_MODIFY_VLAN, 219db810edSAlex Vesker DR_ACTION_STATE_NON_TERM, 229db810edSAlex Vesker DR_ACTION_STATE_TERM, 239db810edSAlex Vesker DR_ACTION_STATE_MAX, 249db810edSAlex Vesker }; 259db810edSAlex Vesker 269db810edSAlex Vesker static const enum dr_action_valid_state 279db810edSAlex Vesker next_action_state[DR_ACTION_DOMAIN_MAX][DR_ACTION_STATE_MAX][DR_ACTION_TYP_MAX] = { 289db810edSAlex Vesker [DR_ACTION_DOMAIN_NIC_INGRESS] = { 299db810edSAlex Vesker [DR_ACTION_STATE_NO_ACTION] = { 309db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 319db810edSAlex Vesker [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM, 329db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 339db810edSAlex Vesker [DR_ACTION_TYP_TAG] = DR_ACTION_STATE_NON_TERM, 349db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM, 35*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_TNL_L2_TO_L2] = DR_ACTION_STATE_DECAP, 36*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_TNL_L3_TO_L2] = DR_ACTION_STATE_DECAP, 379db810edSAlex Vesker [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR, 389db810edSAlex Vesker [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 399db810edSAlex Vesker }, 40*28de41a4SYevgeny Kliteynik [DR_ACTION_STATE_DECAP] = { 419db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 429db810edSAlex Vesker [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM, 439db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 44*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_TAG] = DR_ACTION_STATE_DECAP, 45*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_DECAP, 469db810edSAlex Vesker [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR, 479db810edSAlex Vesker [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 489db810edSAlex Vesker }, 499db810edSAlex Vesker [DR_ACTION_STATE_MODIFY_HDR] = { 509db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 519db810edSAlex Vesker [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM, 529db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 539db810edSAlex Vesker [DR_ACTION_TYP_TAG] = DR_ACTION_STATE_MODIFY_HDR, 549db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_MODIFY_HDR, 559db810edSAlex Vesker }, 569db810edSAlex Vesker [DR_ACTION_STATE_MODIFY_VLAN] = { 579db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 589db810edSAlex Vesker [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM, 599db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 609db810edSAlex Vesker [DR_ACTION_TYP_TAG] = DR_ACTION_STATE_MODIFY_VLAN, 619db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_MODIFY_VLAN, 629db810edSAlex Vesker [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 639db810edSAlex Vesker [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR, 649db810edSAlex Vesker }, 659db810edSAlex Vesker [DR_ACTION_STATE_NON_TERM] = { 669db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 679db810edSAlex Vesker [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM, 689db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 699db810edSAlex Vesker [DR_ACTION_TYP_TAG] = DR_ACTION_STATE_NON_TERM, 709db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM, 71*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_TNL_L2_TO_L2] = DR_ACTION_STATE_DECAP, 72*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_TNL_L3_TO_L2] = DR_ACTION_STATE_DECAP, 739db810edSAlex Vesker [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR, 749db810edSAlex Vesker [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 759db810edSAlex Vesker }, 769db810edSAlex Vesker [DR_ACTION_STATE_TERM] = { 779db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_TERM, 789db810edSAlex Vesker }, 799db810edSAlex Vesker }, 809db810edSAlex Vesker [DR_ACTION_DOMAIN_NIC_EGRESS] = { 819db810edSAlex Vesker [DR_ACTION_STATE_NO_ACTION] = { 829db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 839db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 849db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM, 85*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP, 86*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP, 879db810edSAlex Vesker [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR, 889db810edSAlex Vesker [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 899db810edSAlex Vesker }, 90*28de41a4SYevgeny Kliteynik [DR_ACTION_STATE_ENCAP] = { 919db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 929db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 93*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_ENCAP, 949db810edSAlex Vesker }, 959db810edSAlex Vesker [DR_ACTION_STATE_MODIFY_HDR] = { 969db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 979db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 989db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_MODIFY_HDR, 99*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP, 100*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP, 1019db810edSAlex Vesker [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 1029db810edSAlex Vesker }, 1039db810edSAlex Vesker [DR_ACTION_STATE_MODIFY_VLAN] = { 1049db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 1059db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 1069db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_MODIFY_VLAN, 1079db810edSAlex Vesker [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 108*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP, 109*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP, 1109db810edSAlex Vesker }, 1119db810edSAlex Vesker [DR_ACTION_STATE_NON_TERM] = { 1129db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 1139db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 1149db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM, 115*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP, 116*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP, 1179db810edSAlex Vesker [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR, 1189db810edSAlex Vesker [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 1199db810edSAlex Vesker }, 1209db810edSAlex Vesker [DR_ACTION_STATE_TERM] = { 1219db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_TERM, 1229db810edSAlex Vesker }, 1239db810edSAlex Vesker }, 1249db810edSAlex Vesker [DR_ACTION_DOMAIN_FDB_INGRESS] = { 1259db810edSAlex Vesker [DR_ACTION_STATE_NO_ACTION] = { 1269db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 1279db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 1289db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM, 129*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_TNL_L2_TO_L2] = DR_ACTION_STATE_DECAP, 130*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_TNL_L3_TO_L2] = DR_ACTION_STATE_DECAP, 1319db810edSAlex Vesker [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR, 1329db810edSAlex Vesker [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 1339db810edSAlex Vesker [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM, 1349db810edSAlex Vesker }, 135*28de41a4SYevgeny Kliteynik [DR_ACTION_STATE_DECAP] = { 1369db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 1379db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 138*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_DECAP, 1399db810edSAlex Vesker [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR, 1409db810edSAlex Vesker [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 1419db810edSAlex Vesker [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM, 1429db810edSAlex Vesker }, 1439db810edSAlex Vesker [DR_ACTION_STATE_MODIFY_HDR] = { 1449db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 1459db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 1469db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_MODIFY_HDR, 1479db810edSAlex Vesker [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM, 1489db810edSAlex Vesker }, 1499db810edSAlex Vesker [DR_ACTION_STATE_MODIFY_VLAN] = { 1509db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 1519db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 1529db810edSAlex Vesker [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 1539db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_MODIFY_VLAN, 1549db810edSAlex Vesker [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM, 1559db810edSAlex Vesker [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR, 1569db810edSAlex Vesker }, 1579db810edSAlex Vesker [DR_ACTION_STATE_NON_TERM] = { 1589db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 1599db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 1609db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM, 161*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_TNL_L2_TO_L2] = DR_ACTION_STATE_DECAP, 162*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_TNL_L3_TO_L2] = DR_ACTION_STATE_DECAP, 1639db810edSAlex Vesker [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR, 1649db810edSAlex Vesker [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 1659db810edSAlex Vesker [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM, 1669db810edSAlex Vesker }, 1679db810edSAlex Vesker [DR_ACTION_STATE_TERM] = { 1689db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_TERM, 1699db810edSAlex Vesker }, 1709db810edSAlex Vesker }, 1719db810edSAlex Vesker [DR_ACTION_DOMAIN_FDB_EGRESS] = { 1729db810edSAlex Vesker [DR_ACTION_STATE_NO_ACTION] = { 1739db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 1749db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 1759db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM, 1769db810edSAlex Vesker [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR, 177*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP, 178*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP, 1799db810edSAlex Vesker [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 1809db810edSAlex Vesker [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM, 1819db810edSAlex Vesker }, 182*28de41a4SYevgeny Kliteynik [DR_ACTION_STATE_ENCAP] = { 1839db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 1849db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 185*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_ENCAP, 1869db810edSAlex Vesker [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM, 1879db810edSAlex Vesker }, 1889db810edSAlex Vesker [DR_ACTION_STATE_MODIFY_HDR] = { 1899db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 1909db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 1919db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_MODIFY_HDR, 192*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP, 193*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP, 1949db810edSAlex Vesker [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 1959db810edSAlex Vesker [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM, 1969db810edSAlex Vesker }, 1979db810edSAlex Vesker [DR_ACTION_STATE_MODIFY_VLAN] = { 1989db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 1999db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 2009db810edSAlex Vesker [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 2019db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_MODIFY_VLAN, 202*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP, 203*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP, 2049db810edSAlex Vesker [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM, 2059db810edSAlex Vesker }, 2069db810edSAlex Vesker [DR_ACTION_STATE_NON_TERM] = { 2079db810edSAlex Vesker [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM, 2089db810edSAlex Vesker [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM, 2099db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM, 2109db810edSAlex Vesker [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR, 211*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP, 212*28de41a4SYevgeny Kliteynik [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP, 2139db810edSAlex Vesker [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_MODIFY_VLAN, 2149db810edSAlex Vesker [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM, 2159db810edSAlex Vesker }, 2169db810edSAlex Vesker [DR_ACTION_STATE_TERM] = { 2179db810edSAlex Vesker [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_TERM, 2189db810edSAlex Vesker }, 2199db810edSAlex Vesker }, 2209db810edSAlex Vesker }; 2219db810edSAlex Vesker 2229db810edSAlex Vesker static int 2239db810edSAlex Vesker dr_action_reformat_to_action_type(enum mlx5dr_action_reformat_type reformat_type, 2249db810edSAlex Vesker enum mlx5dr_action_type *action_type) 2259db810edSAlex Vesker { 2269db810edSAlex Vesker switch (reformat_type) { 2279db810edSAlex Vesker case DR_ACTION_REFORMAT_TYP_TNL_L2_TO_L2: 2289db810edSAlex Vesker *action_type = DR_ACTION_TYP_TNL_L2_TO_L2; 2299db810edSAlex Vesker break; 2309db810edSAlex Vesker case DR_ACTION_REFORMAT_TYP_L2_TO_TNL_L2: 2319db810edSAlex Vesker *action_type = DR_ACTION_TYP_L2_TO_TNL_L2; 2329db810edSAlex Vesker break; 2339db810edSAlex Vesker case DR_ACTION_REFORMAT_TYP_TNL_L3_TO_L2: 2349db810edSAlex Vesker *action_type = DR_ACTION_TYP_TNL_L3_TO_L2; 2359db810edSAlex Vesker break; 2369db810edSAlex Vesker case DR_ACTION_REFORMAT_TYP_L2_TO_TNL_L3: 2379db810edSAlex Vesker *action_type = DR_ACTION_TYP_L2_TO_TNL_L3; 2389db810edSAlex Vesker break; 2399db810edSAlex Vesker default: 2409db810edSAlex Vesker return -EINVAL; 2419db810edSAlex Vesker } 2429db810edSAlex Vesker 2439db810edSAlex Vesker return 0; 2449db810edSAlex Vesker } 2459db810edSAlex Vesker 2469db810edSAlex Vesker /* Apply the actions on the rule STE array starting from the last_ste. 2479db810edSAlex Vesker * Actions might require more than one STE, new_num_stes will return 2489db810edSAlex Vesker * the new size of the STEs array, rule with actions. 2499db810edSAlex Vesker */ 2509db810edSAlex Vesker static void dr_actions_apply(struct mlx5dr_domain *dmn, 2519db810edSAlex Vesker enum mlx5dr_ste_entry_type ste_type, 2529db810edSAlex Vesker u8 *action_type_set, 2539db810edSAlex Vesker u8 *last_ste, 25464c78942SYevgeny Kliteynik struct mlx5dr_ste_actions_attr *attr, 2559db810edSAlex Vesker u32 *new_num_stes) 2569db810edSAlex Vesker { 2576b93b400SYevgeny Kliteynik struct mlx5dr_ste_ctx *ste_ctx = dmn->ste_ctx; 2589db810edSAlex Vesker u32 added_stes = 0; 2599db810edSAlex Vesker 2609db810edSAlex Vesker if (ste_type == MLX5DR_STE_TYPE_RX) 2616b93b400SYevgeny Kliteynik mlx5dr_ste_set_actions_rx(ste_ctx, dmn, action_type_set, 26264c78942SYevgeny Kliteynik last_ste, attr, &added_stes); 2639db810edSAlex Vesker else 2646b93b400SYevgeny Kliteynik mlx5dr_ste_set_actions_tx(ste_ctx, dmn, action_type_set, 26564c78942SYevgeny Kliteynik last_ste, attr, &added_stes); 2669db810edSAlex Vesker 2679db810edSAlex Vesker *new_num_stes += added_stes; 2689db810edSAlex Vesker } 2699db810edSAlex Vesker 2709db810edSAlex Vesker static enum dr_action_domain 2719db810edSAlex Vesker dr_action_get_action_domain(enum mlx5dr_domain_type domain, 2729db810edSAlex Vesker enum mlx5dr_ste_entry_type ste_type) 2739db810edSAlex Vesker { 2749db810edSAlex Vesker switch (domain) { 2759db810edSAlex Vesker case MLX5DR_DOMAIN_TYPE_NIC_RX: 2769db810edSAlex Vesker return DR_ACTION_DOMAIN_NIC_INGRESS; 2779db810edSAlex Vesker case MLX5DR_DOMAIN_TYPE_NIC_TX: 2789db810edSAlex Vesker return DR_ACTION_DOMAIN_NIC_EGRESS; 2799db810edSAlex Vesker case MLX5DR_DOMAIN_TYPE_FDB: 2809db810edSAlex Vesker if (ste_type == MLX5DR_STE_TYPE_RX) 2819db810edSAlex Vesker return DR_ACTION_DOMAIN_FDB_INGRESS; 2829db810edSAlex Vesker return DR_ACTION_DOMAIN_FDB_EGRESS; 2839db810edSAlex Vesker default: 2849db810edSAlex Vesker WARN_ON(true); 2859db810edSAlex Vesker return DR_ACTION_DOMAIN_MAX; 2869db810edSAlex Vesker } 2879db810edSAlex Vesker } 2889db810edSAlex Vesker 2899db810edSAlex Vesker static 2909db810edSAlex Vesker int dr_action_validate_and_get_next_state(enum dr_action_domain action_domain, 2919db810edSAlex Vesker u32 action_type, 2929db810edSAlex Vesker u32 *state) 2939db810edSAlex Vesker { 2949db810edSAlex Vesker u32 cur_state = *state; 2959db810edSAlex Vesker 2969db810edSAlex Vesker /* Check action state machine is valid */ 2979db810edSAlex Vesker *state = next_action_state[action_domain][cur_state][action_type]; 2989db810edSAlex Vesker 2999db810edSAlex Vesker if (*state == DR_ACTION_STATE_ERR) 3009db810edSAlex Vesker return -EOPNOTSUPP; 3019db810edSAlex Vesker 3029db810edSAlex Vesker return 0; 3039db810edSAlex Vesker } 3049db810edSAlex Vesker 3059db810edSAlex Vesker static int dr_action_handle_cs_recalc(struct mlx5dr_domain *dmn, 3069db810edSAlex Vesker struct mlx5dr_action *dest_action, 3079db810edSAlex Vesker u64 *final_icm_addr) 3089db810edSAlex Vesker { 3099db810edSAlex Vesker int ret; 3109db810edSAlex Vesker 3119db810edSAlex Vesker switch (dest_action->action_type) { 3129db810edSAlex Vesker case DR_ACTION_TYP_FT: 3139db810edSAlex Vesker /* Allow destination flow table only if table is a terminating 3149db810edSAlex Vesker * table, since there is an *assumption* that in such case FW 3159db810edSAlex Vesker * will recalculate the CS. 3169db810edSAlex Vesker */ 3179dac2966SJianbo Liu if (dest_action->dest_tbl->is_fw_tbl) { 3189dac2966SJianbo Liu *final_icm_addr = dest_action->dest_tbl->fw_tbl.rx_icm_addr; 3199db810edSAlex Vesker } else { 3209db810edSAlex Vesker mlx5dr_dbg(dmn, 3219db810edSAlex Vesker "Destination FT should be terminating when modify TTL is used\n"); 3229db810edSAlex Vesker return -EINVAL; 3239db810edSAlex Vesker } 3249db810edSAlex Vesker break; 3259db810edSAlex Vesker 3269db810edSAlex Vesker case DR_ACTION_TYP_VPORT: 3279db810edSAlex Vesker /* If destination is vport we will get the FW flow table 3289db810edSAlex Vesker * that recalculates the CS and forwards to the vport. 3299db810edSAlex Vesker */ 3309dac2966SJianbo Liu ret = mlx5dr_domain_cache_get_recalc_cs_ft_addr(dest_action->vport->dmn, 3319dac2966SJianbo Liu dest_action->vport->caps->num, 3329db810edSAlex Vesker final_icm_addr); 3339db810edSAlex Vesker if (ret) { 3349db810edSAlex Vesker mlx5dr_err(dmn, "Failed to get FW cs recalc flow table\n"); 3359db810edSAlex Vesker return ret; 3369db810edSAlex Vesker } 3379db810edSAlex Vesker break; 3389db810edSAlex Vesker 3399db810edSAlex Vesker default: 3409db810edSAlex Vesker break; 3419db810edSAlex Vesker } 3429db810edSAlex Vesker 3439db810edSAlex Vesker return 0; 3449db810edSAlex Vesker } 3459db810edSAlex Vesker 3469db810edSAlex Vesker #define WITH_VLAN_NUM_HW_ACTIONS 6 3479db810edSAlex Vesker 3489db810edSAlex Vesker int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher, 3499db810edSAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher, 3509db810edSAlex Vesker struct mlx5dr_action *actions[], 3519db810edSAlex Vesker u32 num_actions, 3529db810edSAlex Vesker u8 *ste_arr, 3539db810edSAlex Vesker u32 *new_hw_ste_arr_sz) 3549db810edSAlex Vesker { 3559db810edSAlex Vesker struct mlx5dr_domain_rx_tx *nic_dmn = nic_matcher->nic_tbl->nic_dmn; 3569db810edSAlex Vesker bool rx_rule = nic_dmn->ste_type == MLX5DR_STE_TYPE_RX; 3579db810edSAlex Vesker struct mlx5dr_domain *dmn = matcher->tbl->dmn; 3589db810edSAlex Vesker u8 action_type_set[DR_ACTION_TYP_MAX] = {}; 35964c78942SYevgeny Kliteynik struct mlx5dr_ste_actions_attr attr = {}; 3609db810edSAlex Vesker struct mlx5dr_action *dest_action = NULL; 3619db810edSAlex Vesker u32 state = DR_ACTION_STATE_NO_ACTION; 3629db810edSAlex Vesker enum dr_action_domain action_domain; 3639db810edSAlex Vesker bool recalc_cs_required = false; 3649db810edSAlex Vesker u8 *last_ste; 3659db810edSAlex Vesker int i, ret; 3669db810edSAlex Vesker 3679db810edSAlex Vesker attr.gvmi = dmn->info.caps.gvmi; 3689db810edSAlex Vesker attr.hit_gvmi = dmn->info.caps.gvmi; 3699db810edSAlex Vesker attr.final_icm_addr = nic_dmn->default_icm_addr; 3709db810edSAlex Vesker action_domain = dr_action_get_action_domain(dmn->type, nic_dmn->ste_type); 3719db810edSAlex Vesker 3729db810edSAlex Vesker for (i = 0; i < num_actions; i++) { 3739dac2966SJianbo Liu struct mlx5dr_action_dest_tbl *dest_tbl; 3749db810edSAlex Vesker struct mlx5dr_action *action; 3759db810edSAlex Vesker int max_actions_type = 1; 3769db810edSAlex Vesker u32 action_type; 3779db810edSAlex Vesker 3789db810edSAlex Vesker action = actions[i]; 3799db810edSAlex Vesker action_type = action->action_type; 3809db810edSAlex Vesker 3819db810edSAlex Vesker switch (action_type) { 3829db810edSAlex Vesker case DR_ACTION_TYP_DROP: 3839db810edSAlex Vesker attr.final_icm_addr = nic_dmn->drop_icm_addr; 3849db810edSAlex Vesker break; 3859db810edSAlex Vesker case DR_ACTION_TYP_FT: 3869db810edSAlex Vesker dest_action = action; 3879dac2966SJianbo Liu dest_tbl = action->dest_tbl; 3889dac2966SJianbo Liu if (!dest_tbl->is_fw_tbl) { 3899dac2966SJianbo Liu if (dest_tbl->tbl->dmn != dmn) { 390b7d0db55SErez Shitrit mlx5dr_err(dmn, 3919db810edSAlex Vesker "Destination table belongs to a different domain\n"); 3929db810edSAlex Vesker goto out_invalid_arg; 3939db810edSAlex Vesker } 3949dac2966SJianbo Liu if (dest_tbl->tbl->level <= matcher->tbl->level) { 3954c7cea2fSYevgeny Kliteynik mlx5_core_warn_once(dmn->mdev, 3964c7cea2fSYevgeny Kliteynik "Connecting table to a lower/same level destination table\n"); 3979db810edSAlex Vesker mlx5dr_dbg(dmn, 3984c7cea2fSYevgeny Kliteynik "Connecting table at level %d to a destination table at level %d\n", 3994c7cea2fSYevgeny Kliteynik matcher->tbl->level, 4009dac2966SJianbo Liu dest_tbl->tbl->level); 4019db810edSAlex Vesker } 4029db810edSAlex Vesker attr.final_icm_addr = rx_rule ? 4039dac2966SJianbo Liu dest_tbl->tbl->rx.s_anchor->chunk->icm_addr : 4049dac2966SJianbo Liu dest_tbl->tbl->tx.s_anchor->chunk->icm_addr; 4059db810edSAlex Vesker } else { 4069db810edSAlex Vesker struct mlx5dr_cmd_query_flow_table_details output; 4079db810edSAlex Vesker int ret; 4089db810edSAlex Vesker 4099db810edSAlex Vesker /* get the relevant addresses */ 4109dac2966SJianbo Liu if (!action->dest_tbl->fw_tbl.rx_icm_addr) { 411aec292eeSAlex Vesker ret = mlx5dr_cmd_query_flow_table(dmn->mdev, 4129dac2966SJianbo Liu dest_tbl->fw_tbl.type, 4139dac2966SJianbo Liu dest_tbl->fw_tbl.id, 4149db810edSAlex Vesker &output); 4159db810edSAlex Vesker if (!ret) { 4169dac2966SJianbo Liu dest_tbl->fw_tbl.tx_icm_addr = 4179db810edSAlex Vesker output.sw_owner_icm_root_1; 4189dac2966SJianbo Liu dest_tbl->fw_tbl.rx_icm_addr = 4199db810edSAlex Vesker output.sw_owner_icm_root_0; 4209db810edSAlex Vesker } else { 421b7d0db55SErez Shitrit mlx5dr_err(dmn, 4229db810edSAlex Vesker "Failed mlx5_cmd_query_flow_table ret: %d\n", 4239db810edSAlex Vesker ret); 4249db810edSAlex Vesker return ret; 4259db810edSAlex Vesker } 4269db810edSAlex Vesker } 4279db810edSAlex Vesker attr.final_icm_addr = rx_rule ? 4289dac2966SJianbo Liu dest_tbl->fw_tbl.rx_icm_addr : 4299dac2966SJianbo Liu dest_tbl->fw_tbl.tx_icm_addr; 4309db810edSAlex Vesker } 4319db810edSAlex Vesker break; 4329db810edSAlex Vesker case DR_ACTION_TYP_QP: 4339db810edSAlex Vesker mlx5dr_info(dmn, "Domain doesn't support QP\n"); 4349db810edSAlex Vesker goto out_invalid_arg; 4359db810edSAlex Vesker case DR_ACTION_TYP_CTR: 4369dac2966SJianbo Liu attr.ctr_id = action->ctr->ctr_id + 4379dac2966SJianbo Liu action->ctr->offeset; 4389db810edSAlex Vesker break; 4399db810edSAlex Vesker case DR_ACTION_TYP_TAG: 4409dac2966SJianbo Liu attr.flow_tag = action->flow_tag->flow_tag; 4419db810edSAlex Vesker break; 4429db810edSAlex Vesker case DR_ACTION_TYP_TNL_L2_TO_L2: 4439db810edSAlex Vesker break; 4449db810edSAlex Vesker case DR_ACTION_TYP_TNL_L3_TO_L2: 4459dac2966SJianbo Liu attr.decap_index = action->rewrite->index; 4469dac2966SJianbo Liu attr.decap_actions = action->rewrite->num_of_actions; 4479db810edSAlex Vesker attr.decap_with_vlan = 4489db810edSAlex Vesker attr.decap_actions == WITH_VLAN_NUM_HW_ACTIONS; 4499db810edSAlex Vesker break; 4509db810edSAlex Vesker case DR_ACTION_TYP_MODIFY_HDR: 4519dac2966SJianbo Liu attr.modify_index = action->rewrite->index; 4529dac2966SJianbo Liu attr.modify_actions = action->rewrite->num_of_actions; 4539dac2966SJianbo Liu recalc_cs_required = action->rewrite->modify_ttl && 454a283ea1bSYevgeny Kliteynik !mlx5dr_ste_supp_ttl_cs_recalc(&dmn->info.caps); 4559db810edSAlex Vesker break; 4569db810edSAlex Vesker case DR_ACTION_TYP_L2_TO_TNL_L2: 4579db810edSAlex Vesker case DR_ACTION_TYP_L2_TO_TNL_L3: 4589dac2966SJianbo Liu attr.reformat_size = action->reformat->reformat_size; 4599dac2966SJianbo Liu attr.reformat_id = action->reformat->reformat_id; 4609db810edSAlex Vesker break; 4619db810edSAlex Vesker case DR_ACTION_TYP_VPORT: 4629dac2966SJianbo Liu attr.hit_gvmi = action->vport->caps->vhca_gvmi; 4639db810edSAlex Vesker dest_action = action; 4649db810edSAlex Vesker if (rx_rule) { 4659db810edSAlex Vesker /* Loopback on WIRE vport is not supported */ 4669dac2966SJianbo Liu if (action->vport->caps->num == WIRE_PORT) 4679db810edSAlex Vesker goto out_invalid_arg; 4689db810edSAlex Vesker 4699dac2966SJianbo Liu attr.final_icm_addr = action->vport->caps->icm_address_rx; 4709db810edSAlex Vesker } else { 4719dac2966SJianbo Liu attr.final_icm_addr = action->vport->caps->icm_address_tx; 4729db810edSAlex Vesker } 4739db810edSAlex Vesker break; 4749db810edSAlex Vesker case DR_ACTION_TYP_POP_VLAN: 47564c78942SYevgeny Kliteynik max_actions_type = MLX5DR_MAX_VLANS; 4769db810edSAlex Vesker attr.vlans.count++; 4779db810edSAlex Vesker break; 4789db810edSAlex Vesker case DR_ACTION_TYP_PUSH_VLAN: 47964c78942SYevgeny Kliteynik max_actions_type = MLX5DR_MAX_VLANS; 48064c78942SYevgeny Kliteynik if (attr.vlans.count == MLX5DR_MAX_VLANS) 4819db810edSAlex Vesker return -EINVAL; 4829db810edSAlex Vesker 4839dac2966SJianbo Liu attr.vlans.headers[attr.vlans.count++] = action->push_vlan->vlan_hdr; 4849db810edSAlex Vesker break; 4859db810edSAlex Vesker default: 4869db810edSAlex Vesker goto out_invalid_arg; 4879db810edSAlex Vesker } 4889db810edSAlex Vesker 4899db810edSAlex Vesker /* Check action duplication */ 4909db810edSAlex Vesker if (++action_type_set[action_type] > max_actions_type) { 491b7d0db55SErez Shitrit mlx5dr_err(dmn, "Action type %d supports only max %d time(s)\n", 4929db810edSAlex Vesker action_type, max_actions_type); 4939db810edSAlex Vesker goto out_invalid_arg; 4949db810edSAlex Vesker } 4959db810edSAlex Vesker 4969db810edSAlex Vesker /* Check action state machine is valid */ 4979db810edSAlex Vesker if (dr_action_validate_and_get_next_state(action_domain, 4989db810edSAlex Vesker action_type, 4999db810edSAlex Vesker &state)) { 500b7d0db55SErez Shitrit mlx5dr_err(dmn, "Invalid action sequence provided\n"); 5019db810edSAlex Vesker return -EOPNOTSUPP; 5029db810edSAlex Vesker } 5039db810edSAlex Vesker } 5049db810edSAlex Vesker 5059db810edSAlex Vesker *new_hw_ste_arr_sz = nic_matcher->num_of_builders; 5069db810edSAlex Vesker last_ste = ste_arr + DR_STE_SIZE * (nic_matcher->num_of_builders - 1); 5079db810edSAlex Vesker 508a283ea1bSYevgeny Kliteynik /* Due to a HW bug in some devices, modifying TTL on RX flows will 509a283ea1bSYevgeny Kliteynik * cause an incorrect checksum calculation. In this case we will 510a283ea1bSYevgeny Kliteynik * use a FW table to recalculate. 5119db810edSAlex Vesker */ 5129db810edSAlex Vesker if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB && 5139db810edSAlex Vesker rx_rule && recalc_cs_required && dest_action) { 5149db810edSAlex Vesker ret = dr_action_handle_cs_recalc(dmn, dest_action, &attr.final_icm_addr); 5159db810edSAlex Vesker if (ret) { 516b7d0db55SErez Shitrit mlx5dr_err(dmn, 5179db810edSAlex Vesker "Failed to handle checksum recalculation err %d\n", 5189db810edSAlex Vesker ret); 5199db810edSAlex Vesker return ret; 5209db810edSAlex Vesker } 5219db810edSAlex Vesker } 5229db810edSAlex Vesker 5239db810edSAlex Vesker dr_actions_apply(dmn, 5249db810edSAlex Vesker nic_dmn->ste_type, 5259db810edSAlex Vesker action_type_set, 5269db810edSAlex Vesker last_ste, 5279db810edSAlex Vesker &attr, 5289db810edSAlex Vesker new_hw_ste_arr_sz); 5299db810edSAlex Vesker 5309db810edSAlex Vesker return 0; 5319db810edSAlex Vesker 5329db810edSAlex Vesker out_invalid_arg: 5339db810edSAlex Vesker return -EINVAL; 5349db810edSAlex Vesker } 5359db810edSAlex Vesker 5369dac2966SJianbo Liu static unsigned int action_size[DR_ACTION_TYP_MAX] = { 5379dac2966SJianbo Liu [DR_ACTION_TYP_TNL_L2_TO_L2] = sizeof(struct mlx5dr_action_reformat), 5389dac2966SJianbo Liu [DR_ACTION_TYP_L2_TO_TNL_L2] = sizeof(struct mlx5dr_action_reformat), 5399dac2966SJianbo Liu [DR_ACTION_TYP_TNL_L3_TO_L2] = sizeof(struct mlx5dr_action_rewrite), 5409dac2966SJianbo Liu [DR_ACTION_TYP_L2_TO_TNL_L3] = sizeof(struct mlx5dr_action_reformat), 5419dac2966SJianbo Liu [DR_ACTION_TYP_FT] = sizeof(struct mlx5dr_action_dest_tbl), 5429dac2966SJianbo Liu [DR_ACTION_TYP_CTR] = sizeof(struct mlx5dr_action_ctr), 5439dac2966SJianbo Liu [DR_ACTION_TYP_TAG] = sizeof(struct mlx5dr_action_flow_tag), 5449dac2966SJianbo Liu [DR_ACTION_TYP_MODIFY_HDR] = sizeof(struct mlx5dr_action_rewrite), 5459dac2966SJianbo Liu [DR_ACTION_TYP_VPORT] = sizeof(struct mlx5dr_action_vport), 5469dac2966SJianbo Liu [DR_ACTION_TYP_PUSH_VLAN] = sizeof(struct mlx5dr_action_push_vlan), 5479dac2966SJianbo Liu }; 5489dac2966SJianbo Liu 5499db810edSAlex Vesker static struct mlx5dr_action * 5509db810edSAlex Vesker dr_action_create_generic(enum mlx5dr_action_type action_type) 5519db810edSAlex Vesker { 5529db810edSAlex Vesker struct mlx5dr_action *action; 5539dac2966SJianbo Liu int extra_size; 5549db810edSAlex Vesker 5559dac2966SJianbo Liu if (action_type < DR_ACTION_TYP_MAX) 5569dac2966SJianbo Liu extra_size = action_size[action_type]; 5579dac2966SJianbo Liu else 5589dac2966SJianbo Liu return NULL; 5599dac2966SJianbo Liu 5609dac2966SJianbo Liu action = kzalloc(sizeof(*action) + extra_size, GFP_KERNEL); 5619db810edSAlex Vesker if (!action) 5629db810edSAlex Vesker return NULL; 5639db810edSAlex Vesker 5649db810edSAlex Vesker action->action_type = action_type; 5659db810edSAlex Vesker refcount_set(&action->refcount, 1); 5669dac2966SJianbo Liu action->data = action + 1; 5679db810edSAlex Vesker 5689db810edSAlex Vesker return action; 5699db810edSAlex Vesker } 5709db810edSAlex Vesker 5719db810edSAlex Vesker struct mlx5dr_action *mlx5dr_action_create_drop(void) 5729db810edSAlex Vesker { 5739db810edSAlex Vesker return dr_action_create_generic(DR_ACTION_TYP_DROP); 5749db810edSAlex Vesker } 5759db810edSAlex Vesker 5769db810edSAlex Vesker struct mlx5dr_action * 577de346f40SAlex Vesker mlx5dr_action_create_dest_table_num(struct mlx5dr_domain *dmn, u32 table_num) 578de346f40SAlex Vesker { 579de346f40SAlex Vesker struct mlx5dr_action *action; 580de346f40SAlex Vesker 581de346f40SAlex Vesker action = dr_action_create_generic(DR_ACTION_TYP_FT); 582de346f40SAlex Vesker if (!action) 583de346f40SAlex Vesker return NULL; 584de346f40SAlex Vesker 5859dac2966SJianbo Liu action->dest_tbl->is_fw_tbl = true; 5869dac2966SJianbo Liu action->dest_tbl->fw_tbl.dmn = dmn; 5879dac2966SJianbo Liu action->dest_tbl->fw_tbl.id = table_num; 5889dac2966SJianbo Liu action->dest_tbl->fw_tbl.type = FS_FT_FDB; 589de346f40SAlex Vesker refcount_inc(&dmn->refcount); 590de346f40SAlex Vesker 591de346f40SAlex Vesker return action; 592de346f40SAlex Vesker } 593de346f40SAlex Vesker 594de346f40SAlex Vesker struct mlx5dr_action * 5959db810edSAlex Vesker mlx5dr_action_create_dest_table(struct mlx5dr_table *tbl) 5969db810edSAlex Vesker { 5979db810edSAlex Vesker struct mlx5dr_action *action; 5989db810edSAlex Vesker 5999db810edSAlex Vesker refcount_inc(&tbl->refcount); 6009db810edSAlex Vesker 6019db810edSAlex Vesker action = dr_action_create_generic(DR_ACTION_TYP_FT); 6029db810edSAlex Vesker if (!action) 6039db810edSAlex Vesker goto dec_ref; 6049db810edSAlex Vesker 6059dac2966SJianbo Liu action->dest_tbl->tbl = tbl; 6069db810edSAlex Vesker 6079db810edSAlex Vesker return action; 6089db810edSAlex Vesker 6099db810edSAlex Vesker dec_ref: 6109db810edSAlex Vesker refcount_dec(&tbl->refcount); 6119db810edSAlex Vesker return NULL; 6129db810edSAlex Vesker } 6139db810edSAlex Vesker 6149db810edSAlex Vesker struct mlx5dr_action * 615b8853c96SAlex Vesker mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn, 616b8853c96SAlex Vesker struct mlx5dr_action_dest *dests, 617b8853c96SAlex Vesker u32 num_of_dests) 618b8853c96SAlex Vesker { 619b8853c96SAlex Vesker struct mlx5dr_cmd_flow_destination_hw_info *hw_dests; 620b8853c96SAlex Vesker struct mlx5dr_action **ref_actions; 621b8853c96SAlex Vesker struct mlx5dr_action *action; 622b8853c96SAlex Vesker bool reformat_req = false; 623b8853c96SAlex Vesker u32 num_of_ref = 0; 624b8853c96SAlex Vesker int ret; 625b8853c96SAlex Vesker int i; 626b8853c96SAlex Vesker 627b8853c96SAlex Vesker if (dmn->type != MLX5DR_DOMAIN_TYPE_FDB) { 628b8853c96SAlex Vesker mlx5dr_err(dmn, "Multiple destination support is for FDB only\n"); 629b8853c96SAlex Vesker return NULL; 630b8853c96SAlex Vesker } 631b8853c96SAlex Vesker 632b8853c96SAlex Vesker hw_dests = kzalloc(sizeof(*hw_dests) * num_of_dests, GFP_KERNEL); 633b8853c96SAlex Vesker if (!hw_dests) 634b8853c96SAlex Vesker return NULL; 635b8853c96SAlex Vesker 636b8853c96SAlex Vesker ref_actions = kzalloc(sizeof(*ref_actions) * num_of_dests * 2, GFP_KERNEL); 637b8853c96SAlex Vesker if (!ref_actions) 638b8853c96SAlex Vesker goto free_hw_dests; 639b8853c96SAlex Vesker 640b8853c96SAlex Vesker for (i = 0; i < num_of_dests; i++) { 641b8853c96SAlex Vesker struct mlx5dr_action *reformat_action = dests[i].reformat; 642b8853c96SAlex Vesker struct mlx5dr_action *dest_action = dests[i].dest; 643b8853c96SAlex Vesker 644b8853c96SAlex Vesker ref_actions[num_of_ref++] = dest_action; 645b8853c96SAlex Vesker 646b8853c96SAlex Vesker switch (dest_action->action_type) { 647b8853c96SAlex Vesker case DR_ACTION_TYP_VPORT: 648b8853c96SAlex Vesker hw_dests[i].vport.flags = MLX5_FLOW_DEST_VPORT_VHCA_ID; 649b8853c96SAlex Vesker hw_dests[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT; 6509dac2966SJianbo Liu hw_dests[i].vport.num = dest_action->vport->caps->num; 6519dac2966SJianbo Liu hw_dests[i].vport.vhca_id = dest_action->vport->caps->vhca_gvmi; 652b8853c96SAlex Vesker if (reformat_action) { 653b8853c96SAlex Vesker reformat_req = true; 654b8853c96SAlex Vesker hw_dests[i].vport.reformat_id = 6559dac2966SJianbo Liu reformat_action->reformat->reformat_id; 656b8853c96SAlex Vesker ref_actions[num_of_ref++] = reformat_action; 657b8853c96SAlex Vesker hw_dests[i].vport.flags |= MLX5_FLOW_DEST_VPORT_REFORMAT_ID; 658b8853c96SAlex Vesker } 659b8853c96SAlex Vesker break; 660b8853c96SAlex Vesker 661b8853c96SAlex Vesker case DR_ACTION_TYP_FT: 662b8853c96SAlex Vesker hw_dests[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 6639dac2966SJianbo Liu if (dest_action->dest_tbl->is_fw_tbl) 6649dac2966SJianbo Liu hw_dests[i].ft_id = dest_action->dest_tbl->fw_tbl.id; 665b8853c96SAlex Vesker else 6669dac2966SJianbo Liu hw_dests[i].ft_id = dest_action->dest_tbl->tbl->table_id; 667b8853c96SAlex Vesker break; 668b8853c96SAlex Vesker 669b8853c96SAlex Vesker default: 670b8853c96SAlex Vesker mlx5dr_dbg(dmn, "Invalid multiple destinations action\n"); 671b8853c96SAlex Vesker goto free_ref_actions; 672b8853c96SAlex Vesker } 673b8853c96SAlex Vesker } 674b8853c96SAlex Vesker 675b8853c96SAlex Vesker action = dr_action_create_generic(DR_ACTION_TYP_FT); 676b8853c96SAlex Vesker if (!action) 677b8853c96SAlex Vesker goto free_ref_actions; 678b8853c96SAlex Vesker 679b8853c96SAlex Vesker ret = mlx5dr_fw_create_md_tbl(dmn, 680b8853c96SAlex Vesker hw_dests, 681b8853c96SAlex Vesker num_of_dests, 682b8853c96SAlex Vesker reformat_req, 6839dac2966SJianbo Liu &action->dest_tbl->fw_tbl.id, 6849dac2966SJianbo Liu &action->dest_tbl->fw_tbl.group_id); 685b8853c96SAlex Vesker if (ret) 686b8853c96SAlex Vesker goto free_action; 687b8853c96SAlex Vesker 688b8853c96SAlex Vesker refcount_inc(&dmn->refcount); 689b8853c96SAlex Vesker 690b8853c96SAlex Vesker for (i = 0; i < num_of_ref; i++) 691b8853c96SAlex Vesker refcount_inc(&ref_actions[i]->refcount); 692b8853c96SAlex Vesker 6939dac2966SJianbo Liu action->dest_tbl->is_fw_tbl = true; 6949dac2966SJianbo Liu action->dest_tbl->fw_tbl.dmn = dmn; 6959dac2966SJianbo Liu action->dest_tbl->fw_tbl.type = FS_FT_FDB; 6969dac2966SJianbo Liu action->dest_tbl->fw_tbl.ref_actions = ref_actions; 6979dac2966SJianbo Liu action->dest_tbl->fw_tbl.num_of_ref_actions = num_of_ref; 698b8853c96SAlex Vesker 699b8853c96SAlex Vesker kfree(hw_dests); 700b8853c96SAlex Vesker 701b8853c96SAlex Vesker return action; 702b8853c96SAlex Vesker 703b8853c96SAlex Vesker free_action: 704b8853c96SAlex Vesker kfree(action); 705b8853c96SAlex Vesker free_ref_actions: 706b8853c96SAlex Vesker kfree(ref_actions); 707b8853c96SAlex Vesker free_hw_dests: 708b8853c96SAlex Vesker kfree(hw_dests); 709b8853c96SAlex Vesker return NULL; 710b8853c96SAlex Vesker } 711b8853c96SAlex Vesker 712b8853c96SAlex Vesker struct mlx5dr_action * 713aec292eeSAlex Vesker mlx5dr_action_create_dest_flow_fw_table(struct mlx5dr_domain *dmn, 714aec292eeSAlex Vesker struct mlx5_flow_table *ft) 7159db810edSAlex Vesker { 7169db810edSAlex Vesker struct mlx5dr_action *action; 7179db810edSAlex Vesker 7189db810edSAlex Vesker action = dr_action_create_generic(DR_ACTION_TYP_FT); 7199db810edSAlex Vesker if (!action) 7209db810edSAlex Vesker return NULL; 7219db810edSAlex Vesker 7229dac2966SJianbo Liu action->dest_tbl->is_fw_tbl = 1; 7239dac2966SJianbo Liu action->dest_tbl->fw_tbl.type = ft->type; 7249dac2966SJianbo Liu action->dest_tbl->fw_tbl.id = ft->id; 7259dac2966SJianbo Liu action->dest_tbl->fw_tbl.dmn = dmn; 726aec292eeSAlex Vesker 727aec292eeSAlex Vesker refcount_inc(&dmn->refcount); 7289db810edSAlex Vesker 7299db810edSAlex Vesker return action; 7309db810edSAlex Vesker } 7319db810edSAlex Vesker 7329db810edSAlex Vesker struct mlx5dr_action * 7339db810edSAlex Vesker mlx5dr_action_create_flow_counter(u32 counter_id) 7349db810edSAlex Vesker { 7359db810edSAlex Vesker struct mlx5dr_action *action; 7369db810edSAlex Vesker 7379db810edSAlex Vesker action = dr_action_create_generic(DR_ACTION_TYP_CTR); 7389db810edSAlex Vesker if (!action) 7399db810edSAlex Vesker return NULL; 7409db810edSAlex Vesker 7419dac2966SJianbo Liu action->ctr->ctr_id = counter_id; 7429db810edSAlex Vesker 7439db810edSAlex Vesker return action; 7449db810edSAlex Vesker } 7459db810edSAlex Vesker 7469db810edSAlex Vesker struct mlx5dr_action *mlx5dr_action_create_tag(u32 tag_value) 7479db810edSAlex Vesker { 7489db810edSAlex Vesker struct mlx5dr_action *action; 7499db810edSAlex Vesker 7509db810edSAlex Vesker action = dr_action_create_generic(DR_ACTION_TYP_TAG); 7519db810edSAlex Vesker if (!action) 7529db810edSAlex Vesker return NULL; 7539db810edSAlex Vesker 7549dac2966SJianbo Liu action->flow_tag->flow_tag = tag_value & 0xffffff; 7559db810edSAlex Vesker 7569db810edSAlex Vesker return action; 7579db810edSAlex Vesker } 7589db810edSAlex Vesker 7599db810edSAlex Vesker static int 7609db810edSAlex Vesker dr_action_verify_reformat_params(enum mlx5dr_action_type reformat_type, 7619db810edSAlex Vesker struct mlx5dr_domain *dmn, 7629db810edSAlex Vesker size_t data_sz, 7639db810edSAlex Vesker void *data) 7649db810edSAlex Vesker { 7659db810edSAlex Vesker if ((!data && data_sz) || (data && !data_sz) || reformat_type > 7669db810edSAlex Vesker DR_ACTION_TYP_L2_TO_TNL_L3) { 7679db810edSAlex Vesker mlx5dr_dbg(dmn, "Invalid reformat parameter!\n"); 7689db810edSAlex Vesker goto out_err; 7699db810edSAlex Vesker } 7709db810edSAlex Vesker 7719db810edSAlex Vesker if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB) 7729db810edSAlex Vesker return 0; 7739db810edSAlex Vesker 7749db810edSAlex Vesker if (dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX) { 7759db810edSAlex Vesker if (reformat_type != DR_ACTION_TYP_TNL_L2_TO_L2 && 7769db810edSAlex Vesker reformat_type != DR_ACTION_TYP_TNL_L3_TO_L2) { 7779db810edSAlex Vesker mlx5dr_dbg(dmn, "Action reformat type not support on RX domain\n"); 7789db810edSAlex Vesker goto out_err; 7799db810edSAlex Vesker } 7809db810edSAlex Vesker } else if (dmn->type == MLX5DR_DOMAIN_TYPE_NIC_TX) { 7819db810edSAlex Vesker if (reformat_type != DR_ACTION_TYP_L2_TO_TNL_L2 && 7829db810edSAlex Vesker reformat_type != DR_ACTION_TYP_L2_TO_TNL_L3) { 7839db810edSAlex Vesker mlx5dr_dbg(dmn, "Action reformat type not support on TX domain\n"); 7849db810edSAlex Vesker goto out_err; 7859db810edSAlex Vesker } 7869db810edSAlex Vesker } 7879db810edSAlex Vesker 7889db810edSAlex Vesker return 0; 7899db810edSAlex Vesker 7909db810edSAlex Vesker out_err: 7919db810edSAlex Vesker return -EINVAL; 7929db810edSAlex Vesker } 7939db810edSAlex Vesker 7949db810edSAlex Vesker #define ACTION_CACHE_LINE_SIZE 64 7959db810edSAlex Vesker 7969db810edSAlex Vesker static int 7979db810edSAlex Vesker dr_action_create_reformat_action(struct mlx5dr_domain *dmn, 7989db810edSAlex Vesker size_t data_sz, void *data, 7999db810edSAlex Vesker struct mlx5dr_action *action) 8009db810edSAlex Vesker { 8019db810edSAlex Vesker u32 reformat_id; 8029db810edSAlex Vesker int ret; 8039db810edSAlex Vesker 8049db810edSAlex Vesker switch (action->action_type) { 8059db810edSAlex Vesker case DR_ACTION_TYP_L2_TO_TNL_L2: 8069db810edSAlex Vesker case DR_ACTION_TYP_L2_TO_TNL_L3: 8079db810edSAlex Vesker { 8087550d541SNathan Chancellor enum mlx5_reformat_ctx_type rt; 8099db810edSAlex Vesker 8109db810edSAlex Vesker if (action->action_type == DR_ACTION_TYP_L2_TO_TNL_L2) 8119db810edSAlex Vesker rt = MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL; 8129db810edSAlex Vesker else 8139db810edSAlex Vesker rt = MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL; 8149db810edSAlex Vesker 8159db810edSAlex Vesker ret = mlx5dr_cmd_create_reformat_ctx(dmn->mdev, rt, data_sz, data, 8169db810edSAlex Vesker &reformat_id); 8179db810edSAlex Vesker if (ret) 8189db810edSAlex Vesker return ret; 8199db810edSAlex Vesker 8209dac2966SJianbo Liu action->reformat->reformat_id = reformat_id; 8219dac2966SJianbo Liu action->reformat->reformat_size = data_sz; 8229db810edSAlex Vesker return 0; 8239db810edSAlex Vesker } 8249db810edSAlex Vesker case DR_ACTION_TYP_TNL_L2_TO_L2: 8259db810edSAlex Vesker { 8269db810edSAlex Vesker return 0; 8279db810edSAlex Vesker } 8289db810edSAlex Vesker case DR_ACTION_TYP_TNL_L3_TO_L2: 8299db810edSAlex Vesker { 8304781df92SYevgeny Kliteynik u8 hw_actions[ACTION_CACHE_LINE_SIZE] = {}; 8314781df92SYevgeny Kliteynik int ret; 8324781df92SYevgeny Kliteynik 8334781df92SYevgeny Kliteynik ret = mlx5dr_ste_set_action_decap_l3_list(dmn->ste_ctx, 8344781df92SYevgeny Kliteynik data, data_sz, 8354781df92SYevgeny Kliteynik hw_actions, 8364781df92SYevgeny Kliteynik ACTION_CACHE_LINE_SIZE, 8379dac2966SJianbo Liu &action->rewrite->num_of_actions); 8384781df92SYevgeny Kliteynik if (ret) { 8394781df92SYevgeny Kliteynik mlx5dr_dbg(dmn, "Failed creating decap l3 action list\n"); 8404781df92SYevgeny Kliteynik return ret; 8414781df92SYevgeny Kliteynik } 8429db810edSAlex Vesker 8439dac2966SJianbo Liu action->rewrite->chunk = mlx5dr_icm_alloc_chunk(dmn->action_icm_pool, 8449db810edSAlex Vesker DR_CHUNK_SIZE_8); 8459dac2966SJianbo Liu if (!action->rewrite->chunk) { 8464781df92SYevgeny Kliteynik mlx5dr_dbg(dmn, "Failed allocating modify header chunk\n"); 8479db810edSAlex Vesker return -ENOMEM; 8484781df92SYevgeny Kliteynik } 8499db810edSAlex Vesker 8509dac2966SJianbo Liu action->rewrite->data = (void *)hw_actions; 8519dac2966SJianbo Liu action->rewrite->index = (action->rewrite->chunk->icm_addr - 8529db810edSAlex Vesker dmn->info.caps.hdr_modify_icm_addr) / 8539db810edSAlex Vesker ACTION_CACHE_LINE_SIZE; 8549db810edSAlex Vesker 8554781df92SYevgeny Kliteynik ret = mlx5dr_send_postsend_action(dmn, action); 8569db810edSAlex Vesker if (ret) { 8574781df92SYevgeny Kliteynik mlx5dr_dbg(dmn, "Writing decap l3 actions to ICM failed\n"); 8589dac2966SJianbo Liu mlx5dr_icm_free_chunk(action->rewrite->chunk); 8599db810edSAlex Vesker return ret; 8609db810edSAlex Vesker } 8619db810edSAlex Vesker return 0; 8629db810edSAlex Vesker } 8639db810edSAlex Vesker default: 8649db810edSAlex Vesker mlx5dr_info(dmn, "Reformat type is not supported %d\n", action->action_type); 8659db810edSAlex Vesker return -EINVAL; 8669db810edSAlex Vesker } 8679db810edSAlex Vesker } 8689db810edSAlex Vesker 8694781df92SYevgeny Kliteynik #define CVLAN_ETHERTYPE 0x8100 8704781df92SYevgeny Kliteynik #define SVLAN_ETHERTYPE 0x88a8 8714781df92SYevgeny Kliteynik 8729db810edSAlex Vesker struct mlx5dr_action *mlx5dr_action_create_pop_vlan(void) 8739db810edSAlex Vesker { 8749db810edSAlex Vesker return dr_action_create_generic(DR_ACTION_TYP_POP_VLAN); 8759db810edSAlex Vesker } 8769db810edSAlex Vesker 8779db810edSAlex Vesker struct mlx5dr_action *mlx5dr_action_create_push_vlan(struct mlx5dr_domain *dmn, 8789db810edSAlex Vesker __be32 vlan_hdr) 8799db810edSAlex Vesker { 8809db810edSAlex Vesker u32 vlan_hdr_h = ntohl(vlan_hdr); 8819db810edSAlex Vesker u16 ethertype = vlan_hdr_h >> 16; 8829db810edSAlex Vesker struct mlx5dr_action *action; 8839db810edSAlex Vesker 8849db810edSAlex Vesker if (ethertype != SVLAN_ETHERTYPE && ethertype != CVLAN_ETHERTYPE) { 8859db810edSAlex Vesker mlx5dr_dbg(dmn, "Invalid vlan ethertype\n"); 8869db810edSAlex Vesker return NULL; 8879db810edSAlex Vesker } 8889db810edSAlex Vesker 8899db810edSAlex Vesker action = dr_action_create_generic(DR_ACTION_TYP_PUSH_VLAN); 8909db810edSAlex Vesker if (!action) 8919db810edSAlex Vesker return NULL; 8929db810edSAlex Vesker 8939dac2966SJianbo Liu action->push_vlan->vlan_hdr = vlan_hdr_h; 8949db810edSAlex Vesker return action; 8959db810edSAlex Vesker } 8969db810edSAlex Vesker 8979db810edSAlex Vesker struct mlx5dr_action * 8989db810edSAlex Vesker mlx5dr_action_create_packet_reformat(struct mlx5dr_domain *dmn, 8999db810edSAlex Vesker enum mlx5dr_action_reformat_type reformat_type, 9009db810edSAlex Vesker size_t data_sz, 9019db810edSAlex Vesker void *data) 9029db810edSAlex Vesker { 9039db810edSAlex Vesker enum mlx5dr_action_type action_type; 9049db810edSAlex Vesker struct mlx5dr_action *action; 9059db810edSAlex Vesker int ret; 9069db810edSAlex Vesker 9079db810edSAlex Vesker refcount_inc(&dmn->refcount); 9089db810edSAlex Vesker 9099db810edSAlex Vesker /* General checks */ 9109db810edSAlex Vesker ret = dr_action_reformat_to_action_type(reformat_type, &action_type); 9119db810edSAlex Vesker if (ret) { 9129db810edSAlex Vesker mlx5dr_dbg(dmn, "Invalid reformat_type provided\n"); 9139db810edSAlex Vesker goto dec_ref; 9149db810edSAlex Vesker } 9159db810edSAlex Vesker 9169db810edSAlex Vesker ret = dr_action_verify_reformat_params(action_type, dmn, data_sz, data); 9179db810edSAlex Vesker if (ret) 9189db810edSAlex Vesker goto dec_ref; 9199db810edSAlex Vesker 9209db810edSAlex Vesker action = dr_action_create_generic(action_type); 9219db810edSAlex Vesker if (!action) 9229db810edSAlex Vesker goto dec_ref; 9239db810edSAlex Vesker 9249dac2966SJianbo Liu action->reformat->dmn = dmn; 9259db810edSAlex Vesker 9269db810edSAlex Vesker ret = dr_action_create_reformat_action(dmn, 9279db810edSAlex Vesker data_sz, 9289db810edSAlex Vesker data, 9299db810edSAlex Vesker action); 9309db810edSAlex Vesker if (ret) { 9319db810edSAlex Vesker mlx5dr_dbg(dmn, "Failed creating reformat action %d\n", ret); 9329db810edSAlex Vesker goto free_action; 9339db810edSAlex Vesker } 9349db810edSAlex Vesker 9359db810edSAlex Vesker return action; 9369db810edSAlex Vesker 9379db810edSAlex Vesker free_action: 9389db810edSAlex Vesker kfree(action); 9399db810edSAlex Vesker dec_ref: 9409db810edSAlex Vesker refcount_dec(&dmn->refcount); 9419db810edSAlex Vesker return NULL; 9429db810edSAlex Vesker } 9439db810edSAlex Vesker 9449db810edSAlex Vesker static int 945a51dcc10SHamdan Igbaria dr_action_modify_sw_to_hw_add(struct mlx5dr_domain *dmn, 9469db810edSAlex Vesker __be64 *sw_action, 9479db810edSAlex Vesker __be64 *hw_action, 9484781df92SYevgeny Kliteynik const struct mlx5dr_ste_action_modify_field **ret_hw_info) 9499db810edSAlex Vesker { 9504781df92SYevgeny Kliteynik const struct mlx5dr_ste_action_modify_field *hw_action_info; 951a51dcc10SHamdan Igbaria u8 max_length; 9529db810edSAlex Vesker u16 sw_field; 9539db810edSAlex Vesker u32 data; 9549db810edSAlex Vesker 9559db810edSAlex Vesker /* Get SW modify action data */ 956a51dcc10SHamdan Igbaria sw_field = MLX5_GET(set_action_in, sw_action, field); 957a51dcc10SHamdan Igbaria data = MLX5_GET(set_action_in, sw_action, data); 958a51dcc10SHamdan Igbaria 959a51dcc10SHamdan Igbaria /* Convert SW data to HW modify action format */ 9604781df92SYevgeny Kliteynik hw_action_info = mlx5dr_ste_conv_modify_hdr_sw_field(dmn->ste_ctx, sw_field); 961a51dcc10SHamdan Igbaria if (!hw_action_info) { 962a51dcc10SHamdan Igbaria mlx5dr_dbg(dmn, "Modify add action invalid field given\n"); 963a51dcc10SHamdan Igbaria return -EINVAL; 964a51dcc10SHamdan Igbaria } 965a51dcc10SHamdan Igbaria 966a51dcc10SHamdan Igbaria max_length = hw_action_info->end - hw_action_info->start + 1; 967a51dcc10SHamdan Igbaria 9684781df92SYevgeny Kliteynik mlx5dr_ste_set_action_add(dmn->ste_ctx, 9694781df92SYevgeny Kliteynik hw_action, 9704781df92SYevgeny Kliteynik hw_action_info->hw_field, 9714781df92SYevgeny Kliteynik hw_action_info->start, 9724781df92SYevgeny Kliteynik max_length, 9734781df92SYevgeny Kliteynik data); 974a51dcc10SHamdan Igbaria 975a51dcc10SHamdan Igbaria *ret_hw_info = hw_action_info; 976a51dcc10SHamdan Igbaria 977a51dcc10SHamdan Igbaria return 0; 978a51dcc10SHamdan Igbaria } 979a51dcc10SHamdan Igbaria 980a51dcc10SHamdan Igbaria static int 981a51dcc10SHamdan Igbaria dr_action_modify_sw_to_hw_set(struct mlx5dr_domain *dmn, 982a51dcc10SHamdan Igbaria __be64 *sw_action, 983a51dcc10SHamdan Igbaria __be64 *hw_action, 9844781df92SYevgeny Kliteynik const struct mlx5dr_ste_action_modify_field **ret_hw_info) 985a51dcc10SHamdan Igbaria { 9864781df92SYevgeny Kliteynik const struct mlx5dr_ste_action_modify_field *hw_action_info; 987a51dcc10SHamdan Igbaria u8 offset, length, max_length; 988a51dcc10SHamdan Igbaria u16 sw_field; 989a51dcc10SHamdan Igbaria u32 data; 990a51dcc10SHamdan Igbaria 991a51dcc10SHamdan Igbaria /* Get SW modify action data */ 9929db810edSAlex Vesker length = MLX5_GET(set_action_in, sw_action, length); 9939db810edSAlex Vesker offset = MLX5_GET(set_action_in, sw_action, offset); 9949db810edSAlex Vesker sw_field = MLX5_GET(set_action_in, sw_action, field); 9959db810edSAlex Vesker data = MLX5_GET(set_action_in, sw_action, data); 9969db810edSAlex Vesker 9979db810edSAlex Vesker /* Convert SW data to HW modify action format */ 9984781df92SYevgeny Kliteynik hw_action_info = mlx5dr_ste_conv_modify_hdr_sw_field(dmn->ste_ctx, sw_field); 9999db810edSAlex Vesker if (!hw_action_info) { 1000a51dcc10SHamdan Igbaria mlx5dr_dbg(dmn, "Modify set action invalid field given\n"); 10019db810edSAlex Vesker return -EINVAL; 10029db810edSAlex Vesker } 10039db810edSAlex Vesker 10049db810edSAlex Vesker /* PRM defines that length zero specific length of 32bits */ 1005a51dcc10SHamdan Igbaria length = length ? length : 32; 1006a51dcc10SHamdan Igbaria 1007a51dcc10SHamdan Igbaria max_length = hw_action_info->end - hw_action_info->start + 1; 10089db810edSAlex Vesker 10099db810edSAlex Vesker if (length + offset > max_length) { 10109db810edSAlex Vesker mlx5dr_dbg(dmn, "Modify action length + offset exceeds limit\n"); 10119db810edSAlex Vesker return -EINVAL; 10129db810edSAlex Vesker } 10139db810edSAlex Vesker 10144781df92SYevgeny Kliteynik mlx5dr_ste_set_action_set(dmn->ste_ctx, 10154781df92SYevgeny Kliteynik hw_action, 10164781df92SYevgeny Kliteynik hw_action_info->hw_field, 10174781df92SYevgeny Kliteynik hw_action_info->start + offset, 10184781df92SYevgeny Kliteynik length, 10194781df92SYevgeny Kliteynik data); 10209db810edSAlex Vesker 10219db810edSAlex Vesker *ret_hw_info = hw_action_info; 10229db810edSAlex Vesker 10239db810edSAlex Vesker return 0; 10249db810edSAlex Vesker } 10259db810edSAlex Vesker 10269db810edSAlex Vesker static int 1027c21a49b3SHamdan Igbaria dr_action_modify_sw_to_hw_copy(struct mlx5dr_domain *dmn, 1028c21a49b3SHamdan Igbaria __be64 *sw_action, 1029c21a49b3SHamdan Igbaria __be64 *hw_action, 10304781df92SYevgeny Kliteynik const struct mlx5dr_ste_action_modify_field **ret_dst_hw_info, 10314781df92SYevgeny Kliteynik const struct mlx5dr_ste_action_modify_field **ret_src_hw_info) 1032c21a49b3SHamdan Igbaria { 1033c21a49b3SHamdan Igbaria u8 src_offset, dst_offset, src_max_length, dst_max_length, length; 10344781df92SYevgeny Kliteynik const struct mlx5dr_ste_action_modify_field *hw_dst_action_info; 10354781df92SYevgeny Kliteynik const struct mlx5dr_ste_action_modify_field *hw_src_action_info; 1036c21a49b3SHamdan Igbaria u16 src_field, dst_field; 1037c21a49b3SHamdan Igbaria 1038c21a49b3SHamdan Igbaria /* Get SW modify action data */ 1039c21a49b3SHamdan Igbaria src_field = MLX5_GET(copy_action_in, sw_action, src_field); 1040c21a49b3SHamdan Igbaria dst_field = MLX5_GET(copy_action_in, sw_action, dst_field); 1041c21a49b3SHamdan Igbaria src_offset = MLX5_GET(copy_action_in, sw_action, src_offset); 1042c21a49b3SHamdan Igbaria dst_offset = MLX5_GET(copy_action_in, sw_action, dst_offset); 1043c21a49b3SHamdan Igbaria length = MLX5_GET(copy_action_in, sw_action, length); 1044c21a49b3SHamdan Igbaria 1045c21a49b3SHamdan Igbaria /* Convert SW data to HW modify action format */ 10464781df92SYevgeny Kliteynik hw_src_action_info = mlx5dr_ste_conv_modify_hdr_sw_field(dmn->ste_ctx, src_field); 10474781df92SYevgeny Kliteynik hw_dst_action_info = mlx5dr_ste_conv_modify_hdr_sw_field(dmn->ste_ctx, dst_field); 1048c21a49b3SHamdan Igbaria if (!hw_src_action_info || !hw_dst_action_info) { 1049c21a49b3SHamdan Igbaria mlx5dr_dbg(dmn, "Modify copy action invalid field given\n"); 1050c21a49b3SHamdan Igbaria return -EINVAL; 1051c21a49b3SHamdan Igbaria } 1052c21a49b3SHamdan Igbaria 1053c21a49b3SHamdan Igbaria /* PRM defines that length zero specific length of 32bits */ 1054c21a49b3SHamdan Igbaria length = length ? length : 32; 1055c21a49b3SHamdan Igbaria 1056c21a49b3SHamdan Igbaria src_max_length = hw_src_action_info->end - 1057c21a49b3SHamdan Igbaria hw_src_action_info->start + 1; 1058c21a49b3SHamdan Igbaria dst_max_length = hw_dst_action_info->end - 1059c21a49b3SHamdan Igbaria hw_dst_action_info->start + 1; 1060c21a49b3SHamdan Igbaria 1061c21a49b3SHamdan Igbaria if (length + src_offset > src_max_length || 1062c21a49b3SHamdan Igbaria length + dst_offset > dst_max_length) { 1063c21a49b3SHamdan Igbaria mlx5dr_dbg(dmn, "Modify action length + offset exceeds limit\n"); 1064c21a49b3SHamdan Igbaria return -EINVAL; 1065c21a49b3SHamdan Igbaria } 1066c21a49b3SHamdan Igbaria 10674781df92SYevgeny Kliteynik mlx5dr_ste_set_action_copy(dmn->ste_ctx, 10684781df92SYevgeny Kliteynik hw_action, 10694781df92SYevgeny Kliteynik hw_dst_action_info->hw_field, 10704781df92SYevgeny Kliteynik hw_dst_action_info->start + dst_offset, 10714781df92SYevgeny Kliteynik length, 10724781df92SYevgeny Kliteynik hw_src_action_info->hw_field, 10734781df92SYevgeny Kliteynik hw_src_action_info->start + src_offset); 1074c21a49b3SHamdan Igbaria 1075c21a49b3SHamdan Igbaria *ret_dst_hw_info = hw_dst_action_info; 1076c21a49b3SHamdan Igbaria *ret_src_hw_info = hw_src_action_info; 1077c21a49b3SHamdan Igbaria 1078c21a49b3SHamdan Igbaria return 0; 1079c21a49b3SHamdan Igbaria } 1080c21a49b3SHamdan Igbaria 1081c21a49b3SHamdan Igbaria static int 1082a51dcc10SHamdan Igbaria dr_action_modify_sw_to_hw(struct mlx5dr_domain *dmn, 1083a51dcc10SHamdan Igbaria __be64 *sw_action, 1084a51dcc10SHamdan Igbaria __be64 *hw_action, 10854781df92SYevgeny Kliteynik const struct mlx5dr_ste_action_modify_field **ret_dst_hw_info, 10864781df92SYevgeny Kliteynik const struct mlx5dr_ste_action_modify_field **ret_src_hw_info) 10879db810edSAlex Vesker { 10889db810edSAlex Vesker u8 action; 1089a51dcc10SHamdan Igbaria int ret; 10909db810edSAlex Vesker 1091a51dcc10SHamdan Igbaria *hw_action = 0; 1092c21a49b3SHamdan Igbaria *ret_src_hw_info = NULL; 1093a51dcc10SHamdan Igbaria 1094a51dcc10SHamdan Igbaria /* Get SW modify action type */ 10959db810edSAlex Vesker action = MLX5_GET(set_action_in, sw_action, action_type); 10969db810edSAlex Vesker 1097a51dcc10SHamdan Igbaria switch (action) { 1098a51dcc10SHamdan Igbaria case MLX5_ACTION_TYPE_SET: 1099a51dcc10SHamdan Igbaria ret = dr_action_modify_sw_to_hw_set(dmn, sw_action, 1100a51dcc10SHamdan Igbaria hw_action, 1101c21a49b3SHamdan Igbaria ret_dst_hw_info); 1102a51dcc10SHamdan Igbaria break; 1103a51dcc10SHamdan Igbaria 1104a51dcc10SHamdan Igbaria case MLX5_ACTION_TYPE_ADD: 1105a51dcc10SHamdan Igbaria ret = dr_action_modify_sw_to_hw_add(dmn, sw_action, 1106a51dcc10SHamdan Igbaria hw_action, 1107c21a49b3SHamdan Igbaria ret_dst_hw_info); 1108c21a49b3SHamdan Igbaria break; 1109c21a49b3SHamdan Igbaria 1110c21a49b3SHamdan Igbaria case MLX5_ACTION_TYPE_COPY: 1111c21a49b3SHamdan Igbaria ret = dr_action_modify_sw_to_hw_copy(dmn, sw_action, 1112c21a49b3SHamdan Igbaria hw_action, 1113c21a49b3SHamdan Igbaria ret_dst_hw_info, 1114c21a49b3SHamdan Igbaria ret_src_hw_info); 1115a51dcc10SHamdan Igbaria break; 1116a51dcc10SHamdan Igbaria 1117a51dcc10SHamdan Igbaria default: 1118a51dcc10SHamdan Igbaria mlx5dr_info(dmn, "Unsupported action_type for modify action\n"); 1119a51dcc10SHamdan Igbaria ret = -EOPNOTSUPP; 1120a51dcc10SHamdan Igbaria } 1121a51dcc10SHamdan Igbaria 1122a51dcc10SHamdan Igbaria return ret; 1123a51dcc10SHamdan Igbaria } 1124a51dcc10SHamdan Igbaria 1125a51dcc10SHamdan Igbaria static int 1126a51dcc10SHamdan Igbaria dr_action_modify_check_set_field_limitation(struct mlx5dr_action *action, 1127a51dcc10SHamdan Igbaria const __be64 *sw_action) 1128a51dcc10SHamdan Igbaria { 1129a51dcc10SHamdan Igbaria u16 sw_field = MLX5_GET(set_action_in, sw_action, field); 11309dac2966SJianbo Liu struct mlx5dr_domain *dmn = action->rewrite->dmn; 1131a51dcc10SHamdan Igbaria 11329db810edSAlex Vesker if (sw_field == MLX5_ACTION_IN_FIELD_METADATA_REG_A) { 11339dac2966SJianbo Liu action->rewrite->allow_rx = 0; 11349db810edSAlex Vesker if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_TX) { 11359db810edSAlex Vesker mlx5dr_dbg(dmn, "Unsupported field %d for RX/FDB set action\n", 11369db810edSAlex Vesker sw_field); 11379db810edSAlex Vesker return -EINVAL; 11389db810edSAlex Vesker } 1139a51dcc10SHamdan Igbaria } else if (sw_field == MLX5_ACTION_IN_FIELD_METADATA_REG_B) { 11409dac2966SJianbo Liu action->rewrite->allow_tx = 0; 11419db810edSAlex Vesker if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_RX) { 11429db810edSAlex Vesker mlx5dr_dbg(dmn, "Unsupported field %d for TX/FDB set action\n", 11439db810edSAlex Vesker sw_field); 11449db810edSAlex Vesker return -EINVAL; 11459db810edSAlex Vesker } 11469db810edSAlex Vesker } 1147a51dcc10SHamdan Igbaria 11489dac2966SJianbo Liu if (!action->rewrite->allow_rx && !action->rewrite->allow_tx) { 1149a51dcc10SHamdan Igbaria mlx5dr_dbg(dmn, "Modify SET actions not supported on both RX and TX\n"); 1150a51dcc10SHamdan Igbaria return -EINVAL; 1151a51dcc10SHamdan Igbaria } 1152a51dcc10SHamdan Igbaria 1153a51dcc10SHamdan Igbaria return 0; 1154a51dcc10SHamdan Igbaria } 1155a51dcc10SHamdan Igbaria 1156a51dcc10SHamdan Igbaria static int 1157a51dcc10SHamdan Igbaria dr_action_modify_check_add_field_limitation(struct mlx5dr_action *action, 1158a51dcc10SHamdan Igbaria const __be64 *sw_action) 1159a51dcc10SHamdan Igbaria { 1160a51dcc10SHamdan Igbaria u16 sw_field = MLX5_GET(set_action_in, sw_action, field); 11619dac2966SJianbo Liu struct mlx5dr_domain *dmn = action->rewrite->dmn; 1162a51dcc10SHamdan Igbaria 11639db810edSAlex Vesker if (sw_field != MLX5_ACTION_IN_FIELD_OUT_IP_TTL && 11649db810edSAlex Vesker sw_field != MLX5_ACTION_IN_FIELD_OUT_IPV6_HOPLIMIT && 11659db810edSAlex Vesker sw_field != MLX5_ACTION_IN_FIELD_OUT_TCP_SEQ_NUM && 11669db810edSAlex Vesker sw_field != MLX5_ACTION_IN_FIELD_OUT_TCP_ACK_NUM) { 1167a51dcc10SHamdan Igbaria mlx5dr_dbg(dmn, "Unsupported field %d for add action\n", 1168a51dcc10SHamdan Igbaria sw_field); 11699db810edSAlex Vesker return -EINVAL; 11709db810edSAlex Vesker } 11719db810edSAlex Vesker 11729db810edSAlex Vesker return 0; 11739db810edSAlex Vesker } 11749db810edSAlex Vesker 1175a51dcc10SHamdan Igbaria static int 1176c21a49b3SHamdan Igbaria dr_action_modify_check_copy_field_limitation(struct mlx5dr_action *action, 1177c21a49b3SHamdan Igbaria const __be64 *sw_action) 1178c21a49b3SHamdan Igbaria { 11799dac2966SJianbo Liu struct mlx5dr_domain *dmn = action->rewrite->dmn; 1180c21a49b3SHamdan Igbaria u16 sw_fields[2]; 1181c21a49b3SHamdan Igbaria int i; 1182c21a49b3SHamdan Igbaria 1183c21a49b3SHamdan Igbaria sw_fields[0] = MLX5_GET(copy_action_in, sw_action, src_field); 1184c21a49b3SHamdan Igbaria sw_fields[1] = MLX5_GET(copy_action_in, sw_action, dst_field); 1185c21a49b3SHamdan Igbaria 1186c21a49b3SHamdan Igbaria for (i = 0; i < 2; i++) { 1187c21a49b3SHamdan Igbaria if (sw_fields[i] == MLX5_ACTION_IN_FIELD_METADATA_REG_A) { 11889dac2966SJianbo Liu action->rewrite->allow_rx = 0; 1189c21a49b3SHamdan Igbaria if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_TX) { 1190c21a49b3SHamdan Igbaria mlx5dr_dbg(dmn, "Unsupported field %d for RX/FDB set action\n", 1191c21a49b3SHamdan Igbaria sw_fields[i]); 1192c21a49b3SHamdan Igbaria return -EINVAL; 1193c21a49b3SHamdan Igbaria } 1194c21a49b3SHamdan Igbaria } else if (sw_fields[i] == MLX5_ACTION_IN_FIELD_METADATA_REG_B) { 11959dac2966SJianbo Liu action->rewrite->allow_tx = 0; 1196c21a49b3SHamdan Igbaria if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_RX) { 1197c21a49b3SHamdan Igbaria mlx5dr_dbg(dmn, "Unsupported field %d for TX/FDB set action\n", 1198c21a49b3SHamdan Igbaria sw_fields[i]); 1199c21a49b3SHamdan Igbaria return -EINVAL; 1200c21a49b3SHamdan Igbaria } 1201c21a49b3SHamdan Igbaria } 1202c21a49b3SHamdan Igbaria } 1203c21a49b3SHamdan Igbaria 12049dac2966SJianbo Liu if (!action->rewrite->allow_rx && !action->rewrite->allow_tx) { 1205c21a49b3SHamdan Igbaria mlx5dr_dbg(dmn, "Modify copy actions not supported on both RX and TX\n"); 1206c21a49b3SHamdan Igbaria return -EINVAL; 1207c21a49b3SHamdan Igbaria } 1208c21a49b3SHamdan Igbaria 1209c21a49b3SHamdan Igbaria return 0; 1210c21a49b3SHamdan Igbaria } 1211c21a49b3SHamdan Igbaria 1212c21a49b3SHamdan Igbaria static int 1213a51dcc10SHamdan Igbaria dr_action_modify_check_field_limitation(struct mlx5dr_action *action, 1214a51dcc10SHamdan Igbaria const __be64 *sw_action) 1215a51dcc10SHamdan Igbaria { 12169dac2966SJianbo Liu struct mlx5dr_domain *dmn = action->rewrite->dmn; 1217a51dcc10SHamdan Igbaria u8 action_type; 1218a51dcc10SHamdan Igbaria int ret; 1219a51dcc10SHamdan Igbaria 1220a51dcc10SHamdan Igbaria action_type = MLX5_GET(set_action_in, sw_action, action_type); 1221a51dcc10SHamdan Igbaria 1222a51dcc10SHamdan Igbaria switch (action_type) { 1223a51dcc10SHamdan Igbaria case MLX5_ACTION_TYPE_SET: 1224a51dcc10SHamdan Igbaria ret = dr_action_modify_check_set_field_limitation(action, 1225a51dcc10SHamdan Igbaria sw_action); 1226a51dcc10SHamdan Igbaria break; 1227a51dcc10SHamdan Igbaria 1228a51dcc10SHamdan Igbaria case MLX5_ACTION_TYPE_ADD: 1229a51dcc10SHamdan Igbaria ret = dr_action_modify_check_add_field_limitation(action, 1230a51dcc10SHamdan Igbaria sw_action); 1231a51dcc10SHamdan Igbaria break; 1232a51dcc10SHamdan Igbaria 1233c21a49b3SHamdan Igbaria case MLX5_ACTION_TYPE_COPY: 1234c21a49b3SHamdan Igbaria ret = dr_action_modify_check_copy_field_limitation(action, 1235c21a49b3SHamdan Igbaria sw_action); 1236c21a49b3SHamdan Igbaria break; 1237c21a49b3SHamdan Igbaria 1238a51dcc10SHamdan Igbaria default: 1239a51dcc10SHamdan Igbaria mlx5dr_info(dmn, "Unsupported action %d modify action\n", 1240a51dcc10SHamdan Igbaria action_type); 1241a51dcc10SHamdan Igbaria ret = -EOPNOTSUPP; 1242a51dcc10SHamdan Igbaria } 1243a51dcc10SHamdan Igbaria 1244a51dcc10SHamdan Igbaria return ret; 1245a51dcc10SHamdan Igbaria } 1246a51dcc10SHamdan Igbaria 12479db810edSAlex Vesker static bool 1248618f88c4SSaeed Mahameed dr_action_modify_check_is_ttl_modify(const void *sw_action) 12499db810edSAlex Vesker { 12509db810edSAlex Vesker u16 sw_field = MLX5_GET(set_action_in, sw_action, field); 12519db810edSAlex Vesker 12529db810edSAlex Vesker return sw_field == MLX5_ACTION_IN_FIELD_OUT_IP_TTL; 12539db810edSAlex Vesker } 12549db810edSAlex Vesker 1255a51dcc10SHamdan Igbaria static int dr_actions_convert_modify_header(struct mlx5dr_action *action, 12569db810edSAlex Vesker u32 max_hw_actions, 12579db810edSAlex Vesker u32 num_sw_actions, 12589db810edSAlex Vesker __be64 sw_actions[], 12599db810edSAlex Vesker __be64 hw_actions[], 12609db810edSAlex Vesker u32 *num_hw_actions, 12619db810edSAlex Vesker bool *modify_ttl) 12629db810edSAlex Vesker { 12634781df92SYevgeny Kliteynik const struct mlx5dr_ste_action_modify_field *hw_dst_action_info; 12644781df92SYevgeny Kliteynik const struct mlx5dr_ste_action_modify_field *hw_src_action_info; 12659dac2966SJianbo Liu struct mlx5dr_domain *dmn = action->rewrite->dmn; 12669db810edSAlex Vesker int ret, i, hw_idx = 0; 12679db810edSAlex Vesker __be64 *sw_action; 12689db810edSAlex Vesker __be64 hw_action; 12694781df92SYevgeny Kliteynik u16 hw_field = 0; 12704781df92SYevgeny Kliteynik u32 l3_type = 0; 12714781df92SYevgeny Kliteynik u32 l4_type = 0; 12729db810edSAlex Vesker 12739db810edSAlex Vesker *modify_ttl = false; 12749db810edSAlex Vesker 12759dac2966SJianbo Liu action->rewrite->allow_rx = 1; 12769dac2966SJianbo Liu action->rewrite->allow_tx = 1; 1277a51dcc10SHamdan Igbaria 12789db810edSAlex Vesker for (i = 0; i < num_sw_actions; i++) { 12799db810edSAlex Vesker sw_action = &sw_actions[i]; 12809db810edSAlex Vesker 1281a51dcc10SHamdan Igbaria ret = dr_action_modify_check_field_limitation(action, 1282a51dcc10SHamdan Igbaria sw_action); 12839db810edSAlex Vesker if (ret) 12849db810edSAlex Vesker return ret; 12859db810edSAlex Vesker 12869db810edSAlex Vesker if (!(*modify_ttl)) 12879db810edSAlex Vesker *modify_ttl = dr_action_modify_check_is_ttl_modify(sw_action); 12889db810edSAlex Vesker 12899db810edSAlex Vesker /* Convert SW action to HW action */ 12909db810edSAlex Vesker ret = dr_action_modify_sw_to_hw(dmn, 12919db810edSAlex Vesker sw_action, 12929db810edSAlex Vesker &hw_action, 1293c21a49b3SHamdan Igbaria &hw_dst_action_info, 1294c21a49b3SHamdan Igbaria &hw_src_action_info); 12959db810edSAlex Vesker if (ret) 12969db810edSAlex Vesker return ret; 12979db810edSAlex Vesker 12989db810edSAlex Vesker /* Due to a HW limitation we cannot modify 2 different L3 types */ 1299c21a49b3SHamdan Igbaria if (l3_type && hw_dst_action_info->l3_type && 1300c21a49b3SHamdan Igbaria hw_dst_action_info->l3_type != l3_type) { 13019db810edSAlex Vesker mlx5dr_dbg(dmn, "Action list can't support two different L3 types\n"); 13029db810edSAlex Vesker return -EINVAL; 13039db810edSAlex Vesker } 1304c21a49b3SHamdan Igbaria if (hw_dst_action_info->l3_type) 1305c21a49b3SHamdan Igbaria l3_type = hw_dst_action_info->l3_type; 13069db810edSAlex Vesker 13079db810edSAlex Vesker /* Due to a HW limitation we cannot modify two different L4 types */ 1308c21a49b3SHamdan Igbaria if (l4_type && hw_dst_action_info->l4_type && 1309c21a49b3SHamdan Igbaria hw_dst_action_info->l4_type != l4_type) { 13109db810edSAlex Vesker mlx5dr_dbg(dmn, "Action list can't support two different L4 types\n"); 13119db810edSAlex Vesker return -EINVAL; 13129db810edSAlex Vesker } 1313c21a49b3SHamdan Igbaria if (hw_dst_action_info->l4_type) 1314c21a49b3SHamdan Igbaria l4_type = hw_dst_action_info->l4_type; 13159db810edSAlex Vesker 13169db810edSAlex Vesker /* HW reads and executes two actions at once this means we 13179db810edSAlex Vesker * need to create a gap if two actions access the same field 13189db810edSAlex Vesker */ 1319c21a49b3SHamdan Igbaria if ((hw_idx % 2) && (hw_field == hw_dst_action_info->hw_field || 1320c21a49b3SHamdan Igbaria (hw_src_action_info && 1321c21a49b3SHamdan Igbaria hw_field == hw_src_action_info->hw_field))) { 13229db810edSAlex Vesker /* Check if after gap insertion the total number of HW 13239db810edSAlex Vesker * modify actions doesn't exceeds the limit 13249db810edSAlex Vesker */ 13259db810edSAlex Vesker hw_idx++; 13269db810edSAlex Vesker if ((num_sw_actions + hw_idx - i) >= max_hw_actions) { 13279db810edSAlex Vesker mlx5dr_dbg(dmn, "Modify header action number exceeds HW limit\n"); 13289db810edSAlex Vesker return -EINVAL; 13299db810edSAlex Vesker } 13309db810edSAlex Vesker } 1331c21a49b3SHamdan Igbaria hw_field = hw_dst_action_info->hw_field; 13329db810edSAlex Vesker 13339db810edSAlex Vesker hw_actions[hw_idx] = hw_action; 13349db810edSAlex Vesker hw_idx++; 13359db810edSAlex Vesker } 13369db810edSAlex Vesker 13379db810edSAlex Vesker *num_hw_actions = hw_idx; 13389db810edSAlex Vesker 13399db810edSAlex Vesker return 0; 13409db810edSAlex Vesker } 13419db810edSAlex Vesker 13429db810edSAlex Vesker static int dr_action_create_modify_action(struct mlx5dr_domain *dmn, 13439db810edSAlex Vesker size_t actions_sz, 13449db810edSAlex Vesker __be64 actions[], 13459db810edSAlex Vesker struct mlx5dr_action *action) 13469db810edSAlex Vesker { 13479db810edSAlex Vesker struct mlx5dr_icm_chunk *chunk; 13489db810edSAlex Vesker u32 max_hw_actions; 13499db810edSAlex Vesker u32 num_hw_actions; 13509db810edSAlex Vesker u32 num_sw_actions; 13519db810edSAlex Vesker __be64 *hw_actions; 13529db810edSAlex Vesker bool modify_ttl; 13539db810edSAlex Vesker int ret; 13549db810edSAlex Vesker 13559db810edSAlex Vesker num_sw_actions = actions_sz / DR_MODIFY_ACTION_SIZE; 13569db810edSAlex Vesker max_hw_actions = mlx5dr_icm_pool_chunk_size_to_entries(DR_CHUNK_SIZE_16); 13579db810edSAlex Vesker 13589db810edSAlex Vesker if (num_sw_actions > max_hw_actions) { 13599db810edSAlex Vesker mlx5dr_dbg(dmn, "Max number of actions %d exceeds limit %d\n", 13609db810edSAlex Vesker num_sw_actions, max_hw_actions); 13619db810edSAlex Vesker return -EINVAL; 13629db810edSAlex Vesker } 13639db810edSAlex Vesker 13649db810edSAlex Vesker chunk = mlx5dr_icm_alloc_chunk(dmn->action_icm_pool, DR_CHUNK_SIZE_16); 13659db810edSAlex Vesker if (!chunk) 13669db810edSAlex Vesker return -ENOMEM; 13679db810edSAlex Vesker 13689db810edSAlex Vesker hw_actions = kcalloc(1, max_hw_actions * DR_MODIFY_ACTION_SIZE, GFP_KERNEL); 13699db810edSAlex Vesker if (!hw_actions) { 13709db810edSAlex Vesker ret = -ENOMEM; 13719db810edSAlex Vesker goto free_chunk; 13729db810edSAlex Vesker } 13739db810edSAlex Vesker 1374a51dcc10SHamdan Igbaria ret = dr_actions_convert_modify_header(action, 13759db810edSAlex Vesker max_hw_actions, 13769db810edSAlex Vesker num_sw_actions, 13779db810edSAlex Vesker actions, 13789db810edSAlex Vesker hw_actions, 13799db810edSAlex Vesker &num_hw_actions, 13809db810edSAlex Vesker &modify_ttl); 13819db810edSAlex Vesker if (ret) 13829db810edSAlex Vesker goto free_hw_actions; 13839db810edSAlex Vesker 13849dac2966SJianbo Liu action->rewrite->chunk = chunk; 13859dac2966SJianbo Liu action->rewrite->modify_ttl = modify_ttl; 13869dac2966SJianbo Liu action->rewrite->data = (u8 *)hw_actions; 13879dac2966SJianbo Liu action->rewrite->num_of_actions = num_hw_actions; 13889dac2966SJianbo Liu action->rewrite->index = (chunk->icm_addr - 13899db810edSAlex Vesker dmn->info.caps.hdr_modify_icm_addr) / 13909db810edSAlex Vesker ACTION_CACHE_LINE_SIZE; 13919db810edSAlex Vesker 13929db810edSAlex Vesker ret = mlx5dr_send_postsend_action(dmn, action); 13939db810edSAlex Vesker if (ret) 13949db810edSAlex Vesker goto free_hw_actions; 13959db810edSAlex Vesker 13969db810edSAlex Vesker return 0; 13979db810edSAlex Vesker 13989db810edSAlex Vesker free_hw_actions: 13999db810edSAlex Vesker kfree(hw_actions); 14009db810edSAlex Vesker free_chunk: 14019db810edSAlex Vesker mlx5dr_icm_free_chunk(chunk); 14029db810edSAlex Vesker return ret; 14039db810edSAlex Vesker } 14049db810edSAlex Vesker 14059db810edSAlex Vesker struct mlx5dr_action * 14069db810edSAlex Vesker mlx5dr_action_create_modify_header(struct mlx5dr_domain *dmn, 14079db810edSAlex Vesker u32 flags, 14089db810edSAlex Vesker size_t actions_sz, 14099db810edSAlex Vesker __be64 actions[]) 14109db810edSAlex Vesker { 14119db810edSAlex Vesker struct mlx5dr_action *action; 14129db810edSAlex Vesker int ret = 0; 14139db810edSAlex Vesker 14149db810edSAlex Vesker refcount_inc(&dmn->refcount); 14159db810edSAlex Vesker 14169db810edSAlex Vesker if (actions_sz % DR_MODIFY_ACTION_SIZE) { 14179db810edSAlex Vesker mlx5dr_dbg(dmn, "Invalid modify actions size provided\n"); 14189db810edSAlex Vesker goto dec_ref; 14199db810edSAlex Vesker } 14209db810edSAlex Vesker 14219db810edSAlex Vesker action = dr_action_create_generic(DR_ACTION_TYP_MODIFY_HDR); 14229db810edSAlex Vesker if (!action) 14239db810edSAlex Vesker goto dec_ref; 14249db810edSAlex Vesker 14259dac2966SJianbo Liu action->rewrite->dmn = dmn; 14269db810edSAlex Vesker 14279db810edSAlex Vesker ret = dr_action_create_modify_action(dmn, 14289db810edSAlex Vesker actions_sz, 14299db810edSAlex Vesker actions, 14309db810edSAlex Vesker action); 14319db810edSAlex Vesker if (ret) { 14329db810edSAlex Vesker mlx5dr_dbg(dmn, "Failed creating modify header action %d\n", ret); 14339db810edSAlex Vesker goto free_action; 14349db810edSAlex Vesker } 14359db810edSAlex Vesker 14369db810edSAlex Vesker return action; 14379db810edSAlex Vesker 14389db810edSAlex Vesker free_action: 14399db810edSAlex Vesker kfree(action); 14409db810edSAlex Vesker dec_ref: 14419db810edSAlex Vesker refcount_dec(&dmn->refcount); 14429db810edSAlex Vesker return NULL; 14439db810edSAlex Vesker } 14449db810edSAlex Vesker 14459db810edSAlex Vesker struct mlx5dr_action * 14469db810edSAlex Vesker mlx5dr_action_create_dest_vport(struct mlx5dr_domain *dmn, 14479db810edSAlex Vesker u32 vport, u8 vhca_id_valid, 14489db810edSAlex Vesker u16 vhca_id) 14499db810edSAlex Vesker { 14509db810edSAlex Vesker struct mlx5dr_cmd_vport_cap *vport_cap; 14519db810edSAlex Vesker struct mlx5dr_domain *vport_dmn; 14529db810edSAlex Vesker struct mlx5dr_action *action; 14539db810edSAlex Vesker u8 peer_vport; 14549db810edSAlex Vesker 14559db810edSAlex Vesker peer_vport = vhca_id_valid && (vhca_id != dmn->info.caps.gvmi); 14569db810edSAlex Vesker vport_dmn = peer_vport ? dmn->peer_dmn : dmn; 14579db810edSAlex Vesker if (!vport_dmn) { 14589db810edSAlex Vesker mlx5dr_dbg(dmn, "No peer vport domain for given vhca_id\n"); 14599db810edSAlex Vesker return NULL; 14609db810edSAlex Vesker } 14619db810edSAlex Vesker 14629db810edSAlex Vesker if (vport_dmn->type != MLX5DR_DOMAIN_TYPE_FDB) { 14639db810edSAlex Vesker mlx5dr_dbg(dmn, "Domain doesn't support vport actions\n"); 14649db810edSAlex Vesker return NULL; 14659db810edSAlex Vesker } 14669db810edSAlex Vesker 14679db810edSAlex Vesker vport_cap = mlx5dr_get_vport_cap(&vport_dmn->info.caps, vport); 14689db810edSAlex Vesker if (!vport_cap) { 14699db810edSAlex Vesker mlx5dr_dbg(dmn, "Failed to get vport %d caps\n", vport); 14709db810edSAlex Vesker return NULL; 14719db810edSAlex Vesker } 14729db810edSAlex Vesker 14739db810edSAlex Vesker action = dr_action_create_generic(DR_ACTION_TYP_VPORT); 14749db810edSAlex Vesker if (!action) 14759db810edSAlex Vesker return NULL; 14769db810edSAlex Vesker 14779dac2966SJianbo Liu action->vport->dmn = vport_dmn; 14789dac2966SJianbo Liu action->vport->caps = vport_cap; 14799db810edSAlex Vesker 14809db810edSAlex Vesker return action; 14819db810edSAlex Vesker } 14829db810edSAlex Vesker 14839db810edSAlex Vesker int mlx5dr_action_destroy(struct mlx5dr_action *action) 14849db810edSAlex Vesker { 14859db810edSAlex Vesker if (refcount_read(&action->refcount) > 1) 14869db810edSAlex Vesker return -EBUSY; 14879db810edSAlex Vesker 14889db810edSAlex Vesker switch (action->action_type) { 14899db810edSAlex Vesker case DR_ACTION_TYP_FT: 14909dac2966SJianbo Liu if (action->dest_tbl->is_fw_tbl) 14919dac2966SJianbo Liu refcount_dec(&action->dest_tbl->fw_tbl.dmn->refcount); 1492aec292eeSAlex Vesker else 14939dac2966SJianbo Liu refcount_dec(&action->dest_tbl->tbl->refcount); 1494b8853c96SAlex Vesker 14959dac2966SJianbo Liu if (action->dest_tbl->is_fw_tbl && 14969dac2966SJianbo Liu action->dest_tbl->fw_tbl.num_of_ref_actions) { 1497b8853c96SAlex Vesker struct mlx5dr_action **ref_actions; 1498b8853c96SAlex Vesker int i; 1499b8853c96SAlex Vesker 15009dac2966SJianbo Liu ref_actions = action->dest_tbl->fw_tbl.ref_actions; 15019dac2966SJianbo Liu for (i = 0; i < action->dest_tbl->fw_tbl.num_of_ref_actions; i++) 1502b8853c96SAlex Vesker refcount_dec(&ref_actions[i]->refcount); 1503b8853c96SAlex Vesker 1504b8853c96SAlex Vesker kfree(ref_actions); 1505b8853c96SAlex Vesker 15069dac2966SJianbo Liu mlx5dr_fw_destroy_md_tbl(action->dest_tbl->fw_tbl.dmn, 15079dac2966SJianbo Liu action->dest_tbl->fw_tbl.id, 15089dac2966SJianbo Liu action->dest_tbl->fw_tbl.group_id); 1509b8853c96SAlex Vesker } 15109db810edSAlex Vesker break; 15119db810edSAlex Vesker case DR_ACTION_TYP_TNL_L2_TO_L2: 15129dac2966SJianbo Liu refcount_dec(&action->reformat->dmn->refcount); 15139db810edSAlex Vesker break; 15149db810edSAlex Vesker case DR_ACTION_TYP_TNL_L3_TO_L2: 15159dac2966SJianbo Liu mlx5dr_icm_free_chunk(action->rewrite->chunk); 15169dac2966SJianbo Liu refcount_dec(&action->rewrite->dmn->refcount); 15179db810edSAlex Vesker break; 15189db810edSAlex Vesker case DR_ACTION_TYP_L2_TO_TNL_L2: 15199db810edSAlex Vesker case DR_ACTION_TYP_L2_TO_TNL_L3: 15209dac2966SJianbo Liu mlx5dr_cmd_destroy_reformat_ctx((action->reformat->dmn)->mdev, 15219dac2966SJianbo Liu action->reformat->reformat_id); 15229dac2966SJianbo Liu refcount_dec(&action->reformat->dmn->refcount); 15239db810edSAlex Vesker break; 15249db810edSAlex Vesker case DR_ACTION_TYP_MODIFY_HDR: 15259dac2966SJianbo Liu mlx5dr_icm_free_chunk(action->rewrite->chunk); 15269dac2966SJianbo Liu kfree(action->rewrite->data); 15279dac2966SJianbo Liu refcount_dec(&action->rewrite->dmn->refcount); 15289db810edSAlex Vesker break; 15299db810edSAlex Vesker default: 15309db810edSAlex Vesker break; 15319db810edSAlex Vesker } 15329db810edSAlex Vesker 15339db810edSAlex Vesker kfree(action); 15349db810edSAlex Vesker return 0; 15359db810edSAlex Vesker } 1536