|
64 | 64 | PROMISC_CHANGE = BIT(3),
|
65 | 65 | };
|
66 | 66 |
|
| 67 | +static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw); |
| 68 | +static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw); |
| 69 | + |
67 | 70 | /* Vport context events */
|
68 | 71 | #define SRIOV_VPORT_EVENTS (UC_ADDR_CHANGE | \
|
69 | 72 | MC_ADDR_CHANGE | \
|
@@ -268,6 +271,37 @@ esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u16 vport)
|
268 | 271 | return __esw_fdb_set_vport_rule(esw, vport, true, mac_c, mac_v);
|
269 | 272 | }
|
270 | 273 |
|
| 274 | +enum { |
| 275 | + LEGACY_VEPA_PRIO = 0, |
| 276 | + LEGACY_FDB_PRIO, |
| 277 | +}; |
| 278 | + |
| 279 | +static int esw_create_legacy_vepa_table(struct mlx5_eswitch *esw) |
| 280 | +{ |
| 281 | + struct mlx5_core_dev *dev = esw->dev; |
| 282 | + struct mlx5_flow_namespace *root_ns; |
| 283 | + struct mlx5_flow_table *fdb; |
| 284 | + int err; |
| 285 | + |
| 286 | + root_ns = mlx5_get_fdb_sub_ns(dev, 0); |
| 287 | + if (!root_ns) { |
| 288 | + esw_warn(dev, "Failed to get FDB flow namespace\n"); |
| 289 | + return -EOPNOTSUPP; |
| 290 | + } |
| 291 | + |
| 292 | + /* num FTE 2, num FG 2 */ |
| 293 | + fdb = mlx5_create_auto_grouped_flow_table(root_ns, LEGACY_VEPA_PRIO, |
| 294 | + 2, 2, 0, 0); |
| 295 | + if (IS_ERR(fdb)) { |
| 296 | + err = PTR_ERR(fdb); |
| 297 | + esw_warn(dev, "Failed to create VEPA FDB err %d\n", err); |
| 298 | + return err; |
| 299 | + } |
| 300 | + esw->fdb_table.legacy.vepa_fdb = fdb; |
| 301 | + |
| 302 | + return 0; |
| 303 | +} |
| 304 | + |
271 | 305 | static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
|
272 | 306 | {
|
273 | 307 | int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
|
@@ -296,8 +330,8 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
|
296 | 330 | return -ENOMEM;
|
297 | 331 |
|
298 | 332 | table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
|
299 |
| - |
300 | 333 | ft_attr.max_fte = table_size;
|
| 334 | + ft_attr.prio = LEGACY_FDB_PRIO; |
301 | 335 | fdb = mlx5_create_flow_table(root_ns, &ft_attr);
|
302 | 336 | if (IS_ERR(fdb)) {
|
303 | 337 | err = PTR_ERR(fdb);
|
@@ -356,41 +390,65 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
|
356 | 390 | esw->fdb_table.legacy.promisc_grp = g;
|
357 | 391 |
|
358 | 392 | out:
|
359 |
| - if (err) { |
360 |
| - if (!IS_ERR_OR_NULL(esw->fdb_table.legacy.allmulti_grp)) { |
361 |
| - mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp); |
362 |
| - esw->fdb_table.legacy.allmulti_grp = NULL; |
363 |
| - } |
364 |
| - if (!IS_ERR_OR_NULL(esw->fdb_table.legacy.addr_grp)) { |
365 |
| - mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp); |
366 |
| - esw->fdb_table.legacy.addr_grp = NULL; |
367 |
| - } |
368 |
| - if (!IS_ERR_OR_NULL(esw->fdb_table.legacy.fdb)) { |
369 |
| - mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb); |
370 |
| - esw->fdb_table.legacy.fdb = NULL; |
371 |
| - } |
372 |
| - } |
| 393 | + if (err) |
| 394 | + esw_destroy_legacy_fdb_table(esw); |
373 | 395 |
|
374 | 396 | kvfree(flow_group_in);
|
375 | 397 | return err;
|
376 | 398 | }
|
377 | 399 |
|
| 400 | +static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw) |
| 401 | +{ |
| 402 | + esw_debug(esw->dev, "Destroy VEPA Table\n"); |
| 403 | + if (!esw->fdb_table.legacy.vepa_fdb) |
| 404 | + return; |
| 405 | + |
| 406 | + mlx5_destroy_flow_table(esw->fdb_table.legacy.vepa_fdb); |
| 407 | + esw->fdb_table.legacy.vepa_fdb = NULL; |
| 408 | +} |
| 409 | + |
378 | 410 | static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw)
|
379 | 411 | {
|
| 412 | + esw_debug(esw->dev, "Destroy FDB Table\n"); |
380 | 413 | if (!esw->fdb_table.legacy.fdb)
|
381 | 414 | return;
|
382 | 415 |
|
383 |
| - esw_debug(esw->dev, "Destroy FDB Table\n"); |
384 |
| - mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp); |
385 |
| - mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp); |
386 |
| - mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp); |
| 416 | + if (esw->fdb_table.legacy.promisc_grp) |
| 417 | + mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp); |
| 418 | + if (esw->fdb_table.legacy.allmulti_grp) |
| 419 | + mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp); |
| 420 | + if (esw->fdb_table.legacy.addr_grp) |
| 421 | + mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp); |
387 | 422 | mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb);
|
| 423 | + |
388 | 424 | esw->fdb_table.legacy.fdb = NULL;
|
389 | 425 | esw->fdb_table.legacy.addr_grp = NULL;
|
390 | 426 | esw->fdb_table.legacy.allmulti_grp = NULL;
|
391 | 427 | esw->fdb_table.legacy.promisc_grp = NULL;
|
392 | 428 | }
|
393 | 429 |
|
| 430 | +static int esw_create_legacy_table(struct mlx5_eswitch *esw) |
| 431 | +{ |
| 432 | + int err; |
| 433 | + |
| 434 | + err = esw_create_legacy_vepa_table(esw); |
| 435 | + if (err) |
| 436 | + return err; |
| 437 | + |
| 438 | + err = esw_create_legacy_fdb_table(esw); |
| 439 | + if (err) |
| 440 | + esw_destroy_legacy_vepa_table(esw); |
| 441 | + |
| 442 | + return err; |
| 443 | +} |
| 444 | + |
| 445 | +static void esw_destroy_legacy_table(struct mlx5_eswitch *esw) |
| 446 | +{ |
| 447 | + esw_cleanup_vepa_rules(esw); |
| 448 | + esw_destroy_legacy_fdb_table(esw); |
| 449 | + esw_destroy_legacy_vepa_table(esw); |
| 450 | +} |
| 451 | + |
394 | 452 | /* E-Switch vport UC/MC lists management */
|
395 | 453 | typedef int (*vport_addr_action)(struct mlx5_eswitch *esw,
|
396 | 454 | struct vport_addr *vaddr);
|
@@ -1677,7 +1735,9 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode)
|
1677 | 1735 | mlx5_lag_update(esw->dev);
|
1678 | 1736 |
|
1679 | 1737 | if (mode == SRIOV_LEGACY) {
|
1680 |
| - err = esw_create_legacy_fdb_table(esw); |
| 1738 | + err = esw_create_legacy_table(esw); |
| 1739 | + if (err) |
| 1740 | + goto abort; |
1681 | 1741 | } else {
|
1682 | 1742 | mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
|
1683 | 1743 | mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
|
@@ -1758,7 +1818,7 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw)
|
1758 | 1818 | esw_destroy_tsar(esw);
|
1759 | 1819 |
|
1760 | 1820 | if (esw->mode == SRIOV_LEGACY)
|
1761 |
| - esw_destroy_legacy_fdb_table(esw); |
| 1821 | + esw_destroy_legacy_table(esw); |
1762 | 1822 | else if (esw->mode == SRIOV_OFFLOADS)
|
1763 | 1823 | esw_offloads_cleanup(esw);
|
1764 | 1824 |
|
@@ -2041,6 +2101,127 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
|
2041 | 2101 | return err;
|
2042 | 2102 | }
|
2043 | 2103 |
|
| 2104 | +static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw) |
| 2105 | +{ |
| 2106 | + if (esw->fdb_table.legacy.vepa_uplink_rule) |
| 2107 | + mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule); |
| 2108 | + |
| 2109 | + if (esw->fdb_table.legacy.vepa_star_rule) |
| 2110 | + mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule); |
| 2111 | + |
| 2112 | + esw->fdb_table.legacy.vepa_uplink_rule = NULL; |
| 2113 | + esw->fdb_table.legacy.vepa_star_rule = NULL; |
| 2114 | +} |
| 2115 | + |
| 2116 | +static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw, |
| 2117 | + u8 setting) |
| 2118 | +{ |
| 2119 | + struct mlx5_flow_destination dest = {}; |
| 2120 | + struct mlx5_flow_act flow_act = {}; |
| 2121 | + struct mlx5_flow_handle *flow_rule; |
| 2122 | + struct mlx5_flow_spec *spec; |
| 2123 | + int err = 0; |
| 2124 | + void *misc; |
| 2125 | + |
| 2126 | + if (!setting) { |
| 2127 | + esw_cleanup_vepa_rules(esw); |
| 2128 | + return 0; |
| 2129 | + } |
| 2130 | + |
| 2131 | + if (esw->fdb_table.legacy.vepa_uplink_rule) |
| 2132 | + return 0; |
| 2133 | + |
| 2134 | + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); |
| 2135 | + if (!spec) |
| 2136 | + return -ENOMEM; |
| 2137 | + |
| 2138 | + /* Uplink rule forward uplink traffic to FDB */ |
| 2139 | + misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); |
| 2140 | + MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK); |
| 2141 | + |
| 2142 | + misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); |
| 2143 | + MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); |
| 2144 | + |
| 2145 | + spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS; |
| 2146 | + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; |
| 2147 | + dest.ft = esw->fdb_table.legacy.fdb; |
| 2148 | + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; |
| 2149 | + flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec, |
| 2150 | + &flow_act, &dest, 1); |
| 2151 | + if (IS_ERR(flow_rule)) { |
| 2152 | + err = PTR_ERR(flow_rule); |
| 2153 | + goto out; |
| 2154 | + } else { |
| 2155 | + esw->fdb_table.legacy.vepa_uplink_rule = flow_rule; |
| 2156 | + } |
| 2157 | + |
| 2158 | + /* Star rule to forward all traffic to uplink vport */ |
| 2159 | + memset(spec, 0, sizeof(*spec)); |
| 2160 | + dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; |
| 2161 | + dest.vport.num = MLX5_VPORT_UPLINK; |
| 2162 | + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; |
| 2163 | + flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec, |
| 2164 | + &flow_act, &dest, 1); |
| 2165 | + if (IS_ERR(flow_rule)) { |
| 2166 | + err = PTR_ERR(flow_rule); |
| 2167 | + goto out; |
| 2168 | + } else { |
| 2169 | + esw->fdb_table.legacy.vepa_star_rule = flow_rule; |
| 2170 | + } |
| 2171 | + |
| 2172 | +out: |
| 2173 | + kvfree(spec); |
| 2174 | + if (err) |
| 2175 | + esw_cleanup_vepa_rules(esw); |
| 2176 | + return err; |
| 2177 | +} |
| 2178 | + |
| 2179 | +int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting) |
| 2180 | +{ |
| 2181 | + int err = 0; |
| 2182 | + |
| 2183 | + if (!esw) |
| 2184 | + return -EOPNOTSUPP; |
| 2185 | + |
| 2186 | + if (!ESW_ALLOWED(esw)) |
| 2187 | + return -EPERM; |
| 2188 | + |
| 2189 | + mutex_lock(&esw->state_lock); |
| 2190 | + if (esw->mode != SRIOV_LEGACY) { |
| 2191 | + err = -EOPNOTSUPP; |
| 2192 | + goto out; |
| 2193 | + } |
| 2194 | + |
| 2195 | + err = _mlx5_eswitch_set_vepa_locked(esw, setting); |
| 2196 | + |
| 2197 | +out: |
| 2198 | + mutex_unlock(&esw->state_lock); |
| 2199 | + return err; |
| 2200 | +} |
| 2201 | + |
| 2202 | +int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting) |
| 2203 | +{ |
| 2204 | + int err = 0; |
| 2205 | + |
| 2206 | + if (!esw) |
| 2207 | + return -EOPNOTSUPP; |
| 2208 | + |
| 2209 | + if (!ESW_ALLOWED(esw)) |
| 2210 | + return -EPERM; |
| 2211 | + |
| 2212 | + mutex_lock(&esw->state_lock); |
| 2213 | + if (esw->mode != SRIOV_LEGACY) { |
| 2214 | + err = -EOPNOTSUPP; |
| 2215 | + goto out; |
| 2216 | + } |
| 2217 | + |
| 2218 | + *setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0; |
| 2219 | + |
| 2220 | +out: |
| 2221 | + mutex_unlock(&esw->state_lock); |
| 2222 | + return err; |
| 2223 | +} |
| 2224 | + |
2044 | 2225 | int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
|
2045 | 2226 | int vport, bool setting)
|
2046 | 2227 | {
|
|
0 commit comments