12c0ade80SHans Petter Selasky /*- 22c0ade80SHans Petter Selasky * Copyright (c) 2020-2021, Mellanox Technologies, Ltd. 32c0ade80SHans Petter Selasky * 42c0ade80SHans Petter Selasky * Redistribution and use in source and binary forms, with or without 52c0ade80SHans Petter Selasky * modification, are permitted provided that the following conditions 62c0ade80SHans Petter Selasky * are met: 72c0ade80SHans Petter Selasky * 1. Redistributions of source code must retain the above copyright 82c0ade80SHans Petter Selasky * notice, this list of conditions and the following disclaimer. 92c0ade80SHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright 102c0ade80SHans Petter Selasky * notice, this list of conditions and the following disclaimer in the 112c0ade80SHans Petter Selasky * documentation and/or other materials provided with the distribution. 122c0ade80SHans Petter Selasky * 132c0ade80SHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND 142c0ade80SHans Petter Selasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 152c0ade80SHans Petter Selasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 162c0ade80SHans Petter Selasky * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 172c0ade80SHans Petter Selasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 182c0ade80SHans Petter Selasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 192c0ade80SHans Petter Selasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 202c0ade80SHans Petter Selasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 212c0ade80SHans Petter Selasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 222c0ade80SHans Petter Selasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 232c0ade80SHans Petter Selasky * SUCH DAMAGE. 242c0ade80SHans Petter Selasky */ 252c0ade80SHans Petter Selasky 262c0ade80SHans Petter Selasky #include "opt_inet.h" 272c0ade80SHans Petter Selasky #include "opt_inet6.h" 282c0ade80SHans Petter Selasky 292c0ade80SHans Petter Selasky #include <dev/mlx5/mlx5_en/en.h> 302c0ade80SHans Petter Selasky 312c0ade80SHans Petter Selasky #include <dev/mlx5/mlx5_core/fs_core.h> 322c0ade80SHans Petter Selasky #include <dev/mlx5/mlx5_core/fs_tcp.h> 332c0ade80SHans Petter Selasky #include <dev/mlx5/device.h> 342c0ade80SHans Petter Selasky 352c0ade80SHans Petter Selasky #include <sys/domain.h> 362c0ade80SHans Petter Selasky 372c0ade80SHans Petter Selasky #include <netinet/in_pcb.h> 382c0ade80SHans Petter Selasky 392c0ade80SHans Petter Selasky #if defined(INET) || defined(INET6) 402c0ade80SHans Petter Selasky static void 412c0ade80SHans Petter Selasky accel_fs_tcp_set_ipv4_flow(struct mlx5_flow_spec *spec, struct inpcb *inp) 422c0ade80SHans Petter Selasky { 432c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_protocol); 442c0ade80SHans Petter Selasky MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_protocol, IPPROTO_TCP); 452c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_version); 462c0ade80SHans Petter Selasky MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_version, 4); 472c0ade80SHans Petter Selasky memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, 482c0ade80SHans Petter Selasky outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4), 492c0ade80SHans Petter Selasky &inp->inp_faddr, 4); 502c0ade80SHans Petter Selasky memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, 512c0ade80SHans Petter Selasky outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4), 522c0ade80SHans Petter Selasky &inp->inp_laddr, 4); 532c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 542c0ade80SHans Petter Selasky outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4); 552c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 562c0ade80SHans Petter Selasky outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4); 572c0ade80SHans Petter Selasky } 582c0ade80SHans Petter Selasky #endif 592c0ade80SHans Petter Selasky 602c0ade80SHans Petter Selasky #ifdef INET6 612c0ade80SHans Petter Selasky static void 622c0ade80SHans Petter Selasky accel_fs_tcp_set_ipv6_flow(struct mlx5_flow_spec *spec, struct inpcb *inp) 632c0ade80SHans Petter Selasky { 642c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_protocol); 652c0ade80SHans Petter Selasky MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_protocol, IPPROTO_TCP); 662c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_version); 672c0ade80SHans Petter Selasky MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_version, 6); 682c0ade80SHans Petter Selasky memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, 692c0ade80SHans Petter Selasky outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6), 702c0ade80SHans Petter Selasky &inp->in6p_faddr, 16); 712c0ade80SHans Petter Selasky memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, 722c0ade80SHans Petter Selasky outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6), 732c0ade80SHans Petter Selasky &inp->in6p_laddr, 16); 742c0ade80SHans Petter Selasky memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 752c0ade80SHans Petter Selasky outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6), 762c0ade80SHans Petter Selasky 0xff, 16); 772c0ade80SHans Petter Selasky memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 782c0ade80SHans Petter Selasky outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6), 792c0ade80SHans Petter Selasky 0xff, 16); 802c0ade80SHans Petter Selasky } 812c0ade80SHans Petter Selasky #endif 822c0ade80SHans Petter Selasky 832c0ade80SHans Petter Selasky void 842c0ade80SHans Petter Selasky mlx5e_accel_fs_del_inpcb(struct mlx5_flow_rule *rule) 852c0ade80SHans Petter Selasky { 86b0b87d91SHans Petter Selasky mlx5_del_flow_rule(&rule); 872c0ade80SHans Petter Selasky } 882c0ade80SHans Petter Selasky 892c0ade80SHans Petter Selasky struct mlx5_flow_rule * 902c0ade80SHans Petter Selasky mlx5e_accel_fs_add_inpcb(struct mlx5e_priv *priv, 912c0ade80SHans Petter Selasky struct inpcb *inp, uint32_t tirn, uint32_t flow_tag, 922c0ade80SHans Petter Selasky uint16_t vlan_id) 932c0ade80SHans Petter Selasky { 942c0ade80SHans Petter Selasky struct mlx5_flow_destination dest = {}; 952c0ade80SHans Petter Selasky struct mlx5e_flow_table *ft = NULL; 9675095cd3SJohn Baldwin #if defined(INET) || defined(INET6) 9775095cd3SJohn Baldwin struct mlx5e_accel_fs_tcp *fs_tcp = &priv->fts.accel_tcp; 9875095cd3SJohn Baldwin #endif 992c0ade80SHans Petter Selasky struct mlx5_flow_rule *flow; 1002c0ade80SHans Petter Selasky struct mlx5_flow_spec *spec; 101cb054a49SMark Bloch struct mlx5_flow_act flow_act = { 102cb054a49SMark Bloch .actions = MLX5_FLOW_ACT_ACTIONS_FLOW_TAG, 103cb054a49SMark Bloch .flow_tag = flow_tag, 104cb054a49SMark Bloch }; 1052c0ade80SHans Petter Selasky 1062c0ade80SHans Petter Selasky spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 1072c0ade80SHans Petter Selasky if (!spec) 1082c0ade80SHans Petter Selasky return (ERR_PTR(-ENOMEM)); 1092c0ade80SHans Petter Selasky 1102c0ade80SHans Petter Selasky spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; 1112c0ade80SHans Petter Selasky 1122c0ade80SHans Petter Selasky INP_RLOCK(inp); 1132c0ade80SHans Petter Selasky /* Set VLAN ID to match, if any. */ 1142c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag); 1152c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.first_vid); 1162c0ade80SHans Petter Selasky if (vlan_id != MLX5E_ACCEL_FS_ADD_INPCB_NO_VLAN) { 1172c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, spec->match_value, outer_headers.cvlan_tag); 1182c0ade80SHans Petter Selasky MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid, vlan_id); 1192c0ade80SHans Petter Selasky } 1202c0ade80SHans Petter Selasky 1212c0ade80SHans Petter Selasky /* Set TCP port numbers. */ 1222c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 1232c0ade80SHans Petter Selasky outer_headers.tcp_dport); 1242c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 1252c0ade80SHans Petter Selasky outer_headers.tcp_sport); 1262c0ade80SHans Petter Selasky MLX5_SET(fte_match_param, spec->match_value, outer_headers.tcp_dport, 1272c0ade80SHans Petter Selasky ntohs(inp->inp_lport)); 1282c0ade80SHans Petter Selasky MLX5_SET(fte_match_param, spec->match_value, outer_headers.tcp_sport, 1292c0ade80SHans Petter Selasky ntohs(inp->inp_fport)); 1302c0ade80SHans Petter Selasky 1312c0ade80SHans Petter Selasky /* Set IP addresses. */ 1322c0ade80SHans Petter Selasky switch (INP_SOCKAF(inp->inp_socket)) { 1332c0ade80SHans Petter Selasky #ifdef INET 1342c0ade80SHans Petter Selasky case AF_INET: 1352c0ade80SHans Petter Selasky accel_fs_tcp_set_ipv4_flow(spec, inp); 1362c0ade80SHans Petter Selasky ft = &fs_tcp->tables[MLX5E_ACCEL_FS_IPV4_TCP]; 1372c0ade80SHans Petter Selasky break; 1382c0ade80SHans Petter Selasky #endif 1392c0ade80SHans Petter Selasky #ifdef INET6 1402c0ade80SHans Petter Selasky case AF_INET6: 1412c0ade80SHans Petter Selasky if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 && 1422c0ade80SHans Petter Selasky IN6_IS_ADDR_V4MAPPED(&inp->in6p_faddr)) { 1432c0ade80SHans Petter Selasky accel_fs_tcp_set_ipv4_flow(spec, inp); 1442c0ade80SHans Petter Selasky ft = &fs_tcp->tables[MLX5E_ACCEL_FS_IPV4_TCP]; 1452c0ade80SHans Petter Selasky } else { 1462c0ade80SHans Petter Selasky accel_fs_tcp_set_ipv6_flow(spec, inp); 1472c0ade80SHans Petter Selasky ft = &fs_tcp->tables[MLX5E_ACCEL_FS_IPV6_TCP]; 1482c0ade80SHans Petter Selasky } 1492c0ade80SHans Petter Selasky break; 1502c0ade80SHans Petter Selasky #endif 1512c0ade80SHans Petter Selasky default: 1522c0ade80SHans Petter Selasky break; 1532c0ade80SHans Petter Selasky } 1542c0ade80SHans Petter Selasky INP_RUNLOCK(inp); 1552c0ade80SHans Petter Selasky 1562c0ade80SHans Petter Selasky if (!ft) { 1572c0ade80SHans Petter Selasky flow = ERR_PTR(-EINVAL); 1582c0ade80SHans Petter Selasky goto out; 1592c0ade80SHans Petter Selasky } 1602c0ade80SHans Petter Selasky 1612c0ade80SHans Petter Selasky dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR; 1622c0ade80SHans Petter Selasky dest.tir_num = tirn; 1632c0ade80SHans Petter Selasky 1642c0ade80SHans Petter Selasky flow = mlx5_add_flow_rule(ft->t, spec->match_criteria_enable, 1652c0ade80SHans Petter Selasky spec->match_criteria, 1662c0ade80SHans Petter Selasky spec->match_value, 1672c0ade80SHans Petter Selasky MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, 168cb054a49SMark Bloch &flow_act, 1692c0ade80SHans Petter Selasky &dest); 1702c0ade80SHans Petter Selasky out: 1712c0ade80SHans Petter Selasky kvfree(spec); 1722c0ade80SHans Petter Selasky return (flow); 1732c0ade80SHans Petter Selasky } 1742c0ade80SHans Petter Selasky 1752c0ade80SHans Petter Selasky static int 1762c0ade80SHans Petter Selasky accel_fs_tcp_add_default_rule(struct mlx5e_priv *priv, int type) 1772c0ade80SHans Petter Selasky { 1782c0ade80SHans Petter Selasky static u32 match_criteria[MLX5_ST_SZ_DW(fte_match_param)]; 1792c0ade80SHans Petter Selasky static u32 match_value[MLX5_ST_SZ_DW(fte_match_param)]; 1802c0ade80SHans Petter Selasky struct mlx5_flow_destination dest = {}; 1812c0ade80SHans Petter Selasky struct mlx5e_accel_fs_tcp *fs_tcp; 1822c0ade80SHans Petter Selasky struct mlx5_flow_rule *rule; 183cb054a49SMark Bloch struct mlx5_flow_act flow_act = { 184cb054a49SMark Bloch .actions = MLX5_FLOW_ACT_ACTIONS_FLOW_TAG, 185cb054a49SMark Bloch .flow_tag = MLX5_FS_DEFAULT_FLOW_TAG, 186cb054a49SMark Bloch }; 1872c0ade80SHans Petter Selasky 1882c0ade80SHans Petter Selasky fs_tcp = &priv->fts.accel_tcp; 1892c0ade80SHans Petter Selasky 1902c0ade80SHans Petter Selasky dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 1912c0ade80SHans Petter Selasky 1922c0ade80SHans Petter Selasky /* 1932c0ade80SHans Petter Selasky * Traffic not matched by flow table rules should be forwarded 1942c0ade80SHans Petter Selasky * to the next flow table in order to not be dropped by the 1952c0ade80SHans Petter Selasky * default action. Refer to the diagram in 1962c0ade80SHans Petter Selasky * mlx5_en_flow_table.c for more information about the order 1972c0ade80SHans Petter Selasky * of flow tables. 1982c0ade80SHans Petter Selasky */ 1992c0ade80SHans Petter Selasky dest.ft = (type == MLX5E_ACCEL_FS_TCP_NUM_TYPES - 1) ? 2002c0ade80SHans Petter Selasky priv->fts.vlan.t : fs_tcp->tables[type + 1].t; 2012c0ade80SHans Petter Selasky 2022c0ade80SHans Petter Selasky rule = mlx5_add_flow_rule(fs_tcp->tables[type].t, 0, match_criteria, match_value, 203cb054a49SMark Bloch MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, &flow_act, &dest); 2042c0ade80SHans Petter Selasky if (IS_ERR(rule)) 2052c0ade80SHans Petter Selasky return (PTR_ERR(rule)); 2062c0ade80SHans Petter Selasky 2072c0ade80SHans Petter Selasky fs_tcp->default_rules[type] = rule; 2082c0ade80SHans Petter Selasky return (0); 2092c0ade80SHans Petter Selasky } 2102c0ade80SHans Petter Selasky 2112c0ade80SHans Petter Selasky #define MLX5E_ACCEL_FS_TCP_NUM_GROUPS (2) 2122c0ade80SHans Petter Selasky #define MLX5E_ACCEL_FS_TCP_GROUP1_SIZE (BIT(16) - 1) 2132c0ade80SHans Petter Selasky #define MLX5E_ACCEL_FS_TCP_GROUP2_SIZE (BIT(0)) 2142c0ade80SHans Petter Selasky #define MLX5E_ACCEL_FS_TCP_TABLE_SIZE (MLX5E_ACCEL_FS_TCP_GROUP1_SIZE +\ 2152c0ade80SHans Petter Selasky MLX5E_ACCEL_FS_TCP_GROUP2_SIZE) 2162c0ade80SHans Petter Selasky static int 2172c0ade80SHans Petter Selasky accel_fs_tcp_create_groups(struct mlx5e_flow_table *ft, int type) 2182c0ade80SHans Petter Selasky { 2192c0ade80SHans Petter Selasky int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 2202c0ade80SHans Petter Selasky void *outer_headers_c; 2212c0ade80SHans Petter Selasky int ix = 0; 2222c0ade80SHans Petter Selasky u32 *in; 2232c0ade80SHans Petter Selasky int err; 2242c0ade80SHans Petter Selasky u8 *mc; 2252c0ade80SHans Petter Selasky 2262c0ade80SHans Petter Selasky ft->g = kcalloc(MLX5E_ACCEL_FS_TCP_NUM_GROUPS, sizeof(*ft->g), GFP_KERNEL); 2272c0ade80SHans Petter Selasky in = kvzalloc(inlen, GFP_KERNEL); 2282c0ade80SHans Petter Selasky if (!in || !ft->g) { 2292c0ade80SHans Petter Selasky kfree(ft->g); 2302c0ade80SHans Petter Selasky kvfree(in); 2312c0ade80SHans Petter Selasky return (-ENOMEM); 2322c0ade80SHans Petter Selasky } 2332c0ade80SHans Petter Selasky 2342c0ade80SHans Petter Selasky mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); 2352c0ade80SHans Petter Selasky outer_headers_c = MLX5_ADDR_OF(fte_match_param, mc, outer_headers); 2362c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, ip_protocol); 2372c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, ip_version); 2382c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, cvlan_tag); 2392c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, first_vid); 2402c0ade80SHans Petter Selasky 2412c0ade80SHans Petter Selasky switch (type) { 2422c0ade80SHans Petter Selasky case MLX5E_ACCEL_FS_IPV4_TCP: 2432c0ade80SHans Petter Selasky case MLX5E_ACCEL_FS_IPV6_TCP: 2442c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, tcp_dport); 2452c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, tcp_sport); 2462c0ade80SHans Petter Selasky break; 2472c0ade80SHans Petter Selasky default: 2482c0ade80SHans Petter Selasky err = -EINVAL; 2492c0ade80SHans Petter Selasky goto out; 2502c0ade80SHans Petter Selasky } 2512c0ade80SHans Petter Selasky 2522c0ade80SHans Petter Selasky switch (type) { 2532c0ade80SHans Petter Selasky case MLX5E_ACCEL_FS_IPV4_TCP: 2542c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, 2552c0ade80SHans Petter Selasky src_ipv4_src_ipv6.ipv4_layout.ipv4); 2562c0ade80SHans Petter Selasky MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, 2572c0ade80SHans Petter Selasky dst_ipv4_dst_ipv6.ipv4_layout.ipv4); 2582c0ade80SHans Petter Selasky break; 2592c0ade80SHans Petter Selasky case MLX5E_ACCEL_FS_IPV6_TCP: 2602c0ade80SHans Petter Selasky memset(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c, 2612c0ade80SHans Petter Selasky src_ipv4_src_ipv6.ipv6_layout.ipv6), 2622c0ade80SHans Petter Selasky 0xff, 16); 2632c0ade80SHans Petter Selasky memset(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c, 2642c0ade80SHans Petter Selasky dst_ipv4_dst_ipv6.ipv6_layout.ipv6), 2652c0ade80SHans Petter Selasky 0xff, 16); 2662c0ade80SHans Petter Selasky break; 2672c0ade80SHans Petter Selasky default: 2682c0ade80SHans Petter Selasky err = -EINVAL; 2692c0ade80SHans Petter Selasky goto out; 2702c0ade80SHans Petter Selasky } 2712c0ade80SHans Petter Selasky 2722c0ade80SHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS); 2732c0ade80SHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix); 2742c0ade80SHans Petter Selasky ix += MLX5E_ACCEL_FS_TCP_GROUP1_SIZE; 2752c0ade80SHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1); 2762c0ade80SHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); 2772c0ade80SHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups])) 2782c0ade80SHans Petter Selasky goto err; 2792c0ade80SHans Petter Selasky ft->num_groups++; 2802c0ade80SHans Petter Selasky 2812c0ade80SHans Petter Selasky /* Default Flow Group */ 2822c0ade80SHans Petter Selasky memset(in, 0, inlen); 2832c0ade80SHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix); 2842c0ade80SHans Petter Selasky ix += MLX5E_ACCEL_FS_TCP_GROUP2_SIZE; 2852c0ade80SHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1); 2862c0ade80SHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); 2872c0ade80SHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups])) 2882c0ade80SHans Petter Selasky goto err; 2892c0ade80SHans Petter Selasky ft->num_groups++; 2902c0ade80SHans Petter Selasky 2912c0ade80SHans Petter Selasky kvfree(in); 2922c0ade80SHans Petter Selasky return (0); 2932c0ade80SHans Petter Selasky 2942c0ade80SHans Petter Selasky err: 2952c0ade80SHans Petter Selasky err = PTR_ERR(ft->g[ft->num_groups]); 2962c0ade80SHans Petter Selasky ft->g[ft->num_groups] = NULL; 2972c0ade80SHans Petter Selasky out: 2982c0ade80SHans Petter Selasky kvfree(in); 2992c0ade80SHans Petter Selasky 3002c0ade80SHans Petter Selasky return (err); 3012c0ade80SHans Petter Selasky } 3022c0ade80SHans Petter Selasky 3032c0ade80SHans Petter Selasky static void 3042c0ade80SHans Petter Selasky accel_fs_tcp_destroy_groups(struct mlx5e_flow_table *ft) 3052c0ade80SHans Petter Selasky { 3062c0ade80SHans Petter Selasky int i; 3072c0ade80SHans Petter Selasky 3082c0ade80SHans Petter Selasky for (i = ft->num_groups - 1; i >= 0; i--) { 3092c0ade80SHans Petter Selasky if (!IS_ERR_OR_NULL(ft->g[i])) 3102c0ade80SHans Petter Selasky mlx5_destroy_flow_group(ft->g[i]); 3112c0ade80SHans Petter Selasky ft->g[i] = NULL; 3122c0ade80SHans Petter Selasky } 3132c0ade80SHans Petter Selasky ft->num_groups = 0; 3142c0ade80SHans Petter Selasky } 3152c0ade80SHans Petter Selasky 3162c0ade80SHans Petter Selasky static int 3172c0ade80SHans Petter Selasky accel_fs_tcp_create_table(struct mlx5e_priv *priv, int type) 3182c0ade80SHans Petter Selasky { 3192c0ade80SHans Petter Selasky struct mlx5e_flow_table *ft = &priv->fts.accel_tcp.tables[type]; 3202c0ade80SHans Petter Selasky int err; 3212c0ade80SHans Petter Selasky 3222c0ade80SHans Petter Selasky ft->num_groups = 0; 3232c0ade80SHans Petter Selasky ft->t = mlx5_create_flow_table(priv->fts.accel_tcp.ns, 0, "tcp", 3242c0ade80SHans Petter Selasky MLX5E_ACCEL_FS_TCP_TABLE_SIZE); 3252c0ade80SHans Petter Selasky if (IS_ERR(ft->t)) { 3262c0ade80SHans Petter Selasky err = PTR_ERR(ft->t); 3272c0ade80SHans Petter Selasky ft->t = NULL; 3282c0ade80SHans Petter Selasky return (err); 3292c0ade80SHans Petter Selasky } 3302c0ade80SHans Petter Selasky 3312c0ade80SHans Petter Selasky err = accel_fs_tcp_create_groups(ft, type); 3322c0ade80SHans Petter Selasky if (err) 3332c0ade80SHans Petter Selasky goto err_destroy_flow_table; 3342c0ade80SHans Petter Selasky 3352c0ade80SHans Petter Selasky return (0); 3362c0ade80SHans Petter Selasky 3372c0ade80SHans Petter Selasky err_destroy_flow_table: 3382c0ade80SHans Petter Selasky mlx5_destroy_flow_table(ft->t); 3392c0ade80SHans Petter Selasky ft->t = NULL; 3402c0ade80SHans Petter Selasky return (err); 3412c0ade80SHans Petter Selasky } 3422c0ade80SHans Petter Selasky 3432c0ade80SHans Petter Selasky static void 3442c0ade80SHans Petter Selasky accel_fs_tcp_destroy_table(struct mlx5e_priv *priv, int i) 3452c0ade80SHans Petter Selasky { 3462c0ade80SHans Petter Selasky struct mlx5e_accel_fs_tcp *fs_tcp; 3472c0ade80SHans Petter Selasky struct mlx5e_flow_table *ft; 3482c0ade80SHans Petter Selasky 3492c0ade80SHans Petter Selasky fs_tcp = &priv->fts.accel_tcp; 3502c0ade80SHans Petter Selasky ft = fs_tcp->tables + i; 3512c0ade80SHans Petter Selasky 3522c0ade80SHans Petter Selasky accel_fs_tcp_destroy_groups(ft); 3532c0ade80SHans Petter Selasky kfree(ft->g); 3542c0ade80SHans Petter Selasky ft->g = NULL; 3552c0ade80SHans Petter Selasky mlx5_destroy_flow_table(ft->t); 3562c0ade80SHans Petter Selasky ft->t = NULL; 3572c0ade80SHans Petter Selasky } 3582c0ade80SHans Petter Selasky 3592c0ade80SHans Petter Selasky void 3602c0ade80SHans Petter Selasky mlx5e_accel_fs_tcp_destroy(struct mlx5e_priv *priv) 3612c0ade80SHans Petter Selasky { 3622c0ade80SHans Petter Selasky int i; 3632c0ade80SHans Petter Selasky 3642c0ade80SHans Petter Selasky if (!MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, ft_field_support.outer_ip_version)) 3652c0ade80SHans Petter Selasky return; 3662c0ade80SHans Petter Selasky 3672f7e9a8aSHans Petter Selasky for (i = 0; i < MLX5E_ACCEL_FS_TCP_NUM_TYPES; i++) { 3682f7e9a8aSHans Petter Selasky mlx5_del_flow_rule(&priv->fts.accel_tcp.default_rules[i]); 3692c0ade80SHans Petter Selasky accel_fs_tcp_destroy_table(priv, i); 3702c0ade80SHans Petter Selasky } 3712f7e9a8aSHans Petter Selasky } 3722c0ade80SHans Petter Selasky 3732c0ade80SHans Petter Selasky int 3742c0ade80SHans Petter Selasky mlx5e_accel_fs_tcp_create(struct mlx5e_priv *priv) 3752c0ade80SHans Petter Selasky { 3762c0ade80SHans Petter Selasky int i, err; 3772c0ade80SHans Petter Selasky 3782c0ade80SHans Petter Selasky if (!MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, ft_field_support.outer_ip_version)) 3792c0ade80SHans Petter Selasky return (0); 3802c0ade80SHans Petter Selasky 3812c0ade80SHans Petter Selasky /* Setup namespace pointer. */ 3822c0ade80SHans Petter Selasky priv->fts.accel_tcp.ns = mlx5_get_flow_namespace( 3832c0ade80SHans Petter Selasky priv->mdev, MLX5_FLOW_NAMESPACE_OFFLOADS); 3842c0ade80SHans Petter Selasky 3852c0ade80SHans Petter Selasky /* 3862c0ade80SHans Petter Selasky * Create flow tables first, because the priority level is 3872c0ade80SHans Petter Selasky * assigned at allocation time. 3882c0ade80SHans Petter Selasky */ 3892c0ade80SHans Petter Selasky for (i = 0; i != MLX5E_ACCEL_FS_TCP_NUM_TYPES; i++) { 3902c0ade80SHans Petter Selasky err = accel_fs_tcp_create_table(priv, i); 3912c0ade80SHans Petter Selasky if (err) 3922c0ade80SHans Petter Selasky goto err_destroy_tables; 3932c0ade80SHans Petter Selasky } 3942c0ade80SHans Petter Selasky 3952c0ade80SHans Petter Selasky /* Create default rules last. */ 3962c0ade80SHans Petter Selasky for (i = 0; i != MLX5E_ACCEL_FS_TCP_NUM_TYPES; i++) { 3972c0ade80SHans Petter Selasky err = accel_fs_tcp_add_default_rule(priv, i); 3982c0ade80SHans Petter Selasky if (err) 3992c0ade80SHans Petter Selasky goto err_destroy_rules; 4002c0ade80SHans Petter Selasky } 4012c0ade80SHans Petter Selasky return (0); 4022c0ade80SHans Petter Selasky 4032c0ade80SHans Petter Selasky err_destroy_rules: 4042c0ade80SHans Petter Selasky while (i--) 405b0b87d91SHans Petter Selasky mlx5_del_flow_rule(&priv->fts.accel_tcp.default_rules[i]); 4062c0ade80SHans Petter Selasky i = MLX5E_ACCEL_FS_TCP_NUM_TYPES; 4072c0ade80SHans Petter Selasky 4082c0ade80SHans Petter Selasky err_destroy_tables: 4092c0ade80SHans Petter Selasky while (i--) 4102c0ade80SHans Petter Selasky accel_fs_tcp_destroy_table(priv, i); 4112c0ade80SHans Petter Selasky return (err); 4122c0ade80SHans Petter Selasky } 413