Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/mlx5: Add support for multi underlay QP

Set underlay QPN as part of flow rule when it's applicable.

There is one root flow table in the NIC RX namespace and all the
underlay QPs steer the traffic to this flow table.
In order to prevent QP to get traffic which is not target to its
underlay QP, we need to set the underlay QP number as part of
the steering matching.

Note:
When multicast traffic is sent the QPN filtering is done by the firmware
as some early step. Adding the QPN match on the flow table entry is
wrong as by that time the target QPN holds the multicast address (e.g.
FF(s)) and it won't match.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>

authored by

Yishai Hadas and committed by
Doug Ledford
a550ddfc 7b4cdaae

+48 -9
+42 -7
drivers/infiniband/hw/mlx5/main.c
··· 2125 2125 * it won't fall into the multicast flow steering table and this rule 2126 2126 * could steal other multicast packets. 2127 2127 */ 2128 - static bool flow_is_multicast_only(struct ib_flow_attr *ib_attr) 2128 + static bool flow_is_multicast_only(const struct ib_flow_attr *ib_attr) 2129 2129 { 2130 2130 union ib_flow_spec *flow_spec; 2131 2131 ··· 2337 2337 return err ? ERR_PTR(err) : prio; 2338 2338 } 2339 2339 2340 - static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev, 2341 - struct mlx5_ib_flow_prio *ft_prio, 2342 - const struct ib_flow_attr *flow_attr, 2343 - struct mlx5_flow_destination *dst) 2340 + static void set_underlay_qp(struct mlx5_ib_dev *dev, 2341 + struct mlx5_flow_spec *spec, 2342 + u32 underlay_qpn) 2343 + { 2344 + void *misc_params_c = MLX5_ADDR_OF(fte_match_param, 2345 + spec->match_criteria, 2346 + misc_parameters); 2347 + void *misc_params_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, 2348 + misc_parameters); 2349 + 2350 + if (underlay_qpn && 2351 + MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, 2352 + ft_field_support.bth_dst_qp)) { 2353 + MLX5_SET(fte_match_set_misc, 2354 + misc_params_v, bth_dst_qp, underlay_qpn); 2355 + MLX5_SET(fte_match_set_misc, 2356 + misc_params_c, bth_dst_qp, 0xffffff); 2357 + } 2358 + } 2359 + 2360 + static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev, 2361 + struct mlx5_ib_flow_prio *ft_prio, 2362 + const struct ib_flow_attr *flow_attr, 2363 + struct mlx5_flow_destination *dst, 2364 + u32 underlay_qpn) 2344 2365 { 2345 2366 struct mlx5_flow_table *ft = ft_prio->flow_table; 2346 2367 struct mlx5_ib_flow_handler *handler; ··· 2396 2375 2397 2376 ib_flow += ((union ib_flow_spec *)ib_flow)->size; 2398 2377 } 2378 + 2379 + if (!flow_is_multicast_only(flow_attr)) 2380 + set_underlay_qp(dev, spec, underlay_qpn); 2399 2381 2400 2382 spec->match_criteria_enable = get_match_criteria_enable(spec->match_criteria); 2401 2383 if (is_drop) { ··· 2437 2413 kfree(handler); 2438 2414 kvfree(spec); 2439 2415 return err ? ERR_PTR(err) : handler; 2416 + } 2417 + 2418 + static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev, 2419 + struct mlx5_ib_flow_prio *ft_prio, 2420 + const struct ib_flow_attr *flow_attr, 2421 + struct mlx5_flow_destination *dst) 2422 + { 2423 + return _create_flow_rule(dev, ft_prio, flow_attr, dst, 0); 2440 2424 } 2441 2425 2442 2426 static struct mlx5_ib_flow_handler *create_dont_trap_rule(struct mlx5_ib_dev *dev, ··· 2583 2551 struct mlx5_ib_flow_prio *ft_prio_tx = NULL; 2584 2552 struct mlx5_ib_flow_prio *ft_prio; 2585 2553 int err; 2554 + int underlay_qpn; 2586 2555 2587 2556 if (flow_attr->priority > MLX5_IB_FLOW_LAST_PRIO) 2588 2557 return ERR_PTR(-ENOMEM); ··· 2624 2591 handler = create_dont_trap_rule(dev, ft_prio, 2625 2592 flow_attr, dst); 2626 2593 } else { 2627 - handler = create_flow_rule(dev, ft_prio, flow_attr, 2628 - dst); 2594 + underlay_qpn = (mqp->flags & MLX5_IB_QP_UNDERLAY) ? 2595 + mqp->underlay_qpn : 0; 2596 + handler = _create_flow_rule(dev, ft_prio, flow_attr, 2597 + dst, underlay_qpn); 2629 2598 } 2630 2599 } else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || 2631 2600 flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) {
+6 -2
include/linux/mlx5/mlx5_ifc.h
··· 295 295 u8 inner_tcp_dport[0x1]; 296 296 u8 inner_tcp_flags[0x1]; 297 297 u8 reserved_at_37[0x9]; 298 + u8 reserved_at_40[0x1a]; 299 + u8 bth_dst_qp[0x1]; 298 300 299 - u8 reserved_at_40[0x40]; 301 + u8 reserved_at_5b[0x25]; 300 302 }; 301 303 302 304 struct mlx5_ifc_flow_table_prop_layout_bits { ··· 434 432 u8 reserved_at_100[0xc]; 435 433 u8 inner_ipv6_flow_label[0x14]; 436 434 437 - u8 reserved_at_120[0xe0]; 435 + u8 reserved_at_120[0x28]; 436 + u8 bth_dst_qp[0x18]; 437 + u8 reserved_at_160[0xa0]; 438 438 }; 439 439 440 440 struct mlx5_ifc_cmd_pas_bits {