|
10 | 10 | #include <rdma/uverbs_std_types.h>
|
11 | 11 | #include <rdma/mlx5_user_ioctl_cmds.h>
|
12 | 12 | #include <rdma/mlx5_user_ioctl_verbs.h>
|
| 13 | +#include <rdma/ib_hdrs.h> |
13 | 14 | #include <rdma/ib_umem.h>
|
14 | 15 | #include <linux/mlx5/driver.h>
|
15 | 16 | #include <linux/mlx5/fs.h>
|
16 | 17 | #include <linux/mlx5/fs_helpers.h>
|
17 | 18 | #include <linux/mlx5/accel.h>
|
18 | 19 | #include <linux/mlx5/eswitch.h>
|
| 20 | +#include <net/inet_ecn.h> |
19 | 21 | #include "mlx5_ib.h"
|
20 | 22 | #include "counters.h"
|
21 | 23 | #include "devx.h"
|
@@ -847,6 +849,191 @@ static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
|
847 | 849 | return prio;
|
848 | 850 | }
|
849 | 851 |
|
| 852 | +enum { |
| 853 | + RDMA_RX_ECN_OPCOUNTER_PRIO, |
| 854 | + RDMA_RX_CNP_OPCOUNTER_PRIO, |
| 855 | +}; |
| 856 | + |
| 857 | +enum { |
| 858 | + RDMA_TX_CNP_OPCOUNTER_PRIO, |
| 859 | +}; |
| 860 | + |
| 861 | +static int set_vhca_port_spec(struct mlx5_ib_dev *dev, u32 port_num, |
| 862 | + struct mlx5_flow_spec *spec) |
| 863 | +{ |
| 864 | + if (!MLX5_CAP_FLOWTABLE_RDMA_RX(dev->mdev, |
| 865 | + ft_field_support.source_vhca_port) || |
| 866 | + !MLX5_CAP_FLOWTABLE_RDMA_TX(dev->mdev, |
| 867 | + ft_field_support.source_vhca_port)) |
| 868 | + return -EOPNOTSUPP; |
| 869 | + |
| 870 | + MLX5_SET_TO_ONES(fte_match_param, &spec->match_criteria, |
| 871 | + misc_parameters.source_vhca_port); |
| 872 | + MLX5_SET(fte_match_param, &spec->match_value, |
| 873 | + misc_parameters.source_vhca_port, port_num); |
| 874 | + |
| 875 | + return 0; |
| 876 | +} |
| 877 | + |
| 878 | +static int set_ecn_ce_spec(struct mlx5_ib_dev *dev, u32 port_num, |
| 879 | + struct mlx5_flow_spec *spec, int ipv) |
| 880 | +{ |
| 881 | + if (!MLX5_CAP_FLOWTABLE_RDMA_RX(dev->mdev, |
| 882 | + ft_field_support.outer_ip_version)) |
| 883 | + return -EOPNOTSUPP; |
| 884 | + |
| 885 | + if (mlx5_core_mp_enabled(dev->mdev) && |
| 886 | + set_vhca_port_spec(dev, port_num, spec)) |
| 887 | + return -EOPNOTSUPP; |
| 888 | + |
| 889 | + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, |
| 890 | + outer_headers.ip_ecn); |
| 891 | + MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_ecn, |
| 892 | + INET_ECN_CE); |
| 893 | + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, |
| 894 | + outer_headers.ip_version); |
| 895 | + MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_version, |
| 896 | + ipv); |
| 897 | + |
| 898 | + spec->match_criteria_enable = |
| 899 | + get_match_criteria_enable(spec->match_criteria); |
| 900 | + |
| 901 | + return 0; |
| 902 | +} |
| 903 | + |
| 904 | +static int set_cnp_spec(struct mlx5_ib_dev *dev, u32 port_num, |
| 905 | + struct mlx5_flow_spec *spec) |
| 906 | +{ |
| 907 | + if (mlx5_core_mp_enabled(dev->mdev) && |
| 908 | + set_vhca_port_spec(dev, port_num, spec)) |
| 909 | + return -EOPNOTSUPP; |
| 910 | + |
| 911 | + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, |
| 912 | + misc_parameters.bth_opcode); |
| 913 | + MLX5_SET(fte_match_param, spec->match_value, misc_parameters.bth_opcode, |
| 914 | + IB_BTH_OPCODE_CNP); |
| 915 | + |
| 916 | + spec->match_criteria_enable = |
| 917 | + get_match_criteria_enable(spec->match_criteria); |
| 918 | + |
| 919 | + return 0; |
| 920 | +} |
| 921 | + |
| 922 | +int mlx5_ib_fs_add_op_fc(struct mlx5_ib_dev *dev, u32 port_num, |
| 923 | + struct mlx5_ib_op_fc *opfc, |
| 924 | + enum mlx5_ib_optional_counter_type type) |
| 925 | +{ |
| 926 | + enum mlx5_flow_namespace_type fn_type; |
| 927 | + int priority, i, err, spec_num; |
| 928 | + struct mlx5_flow_act flow_act = {}; |
| 929 | + struct mlx5_flow_destination dst; |
| 930 | + struct mlx5_flow_namespace *ns; |
| 931 | + struct mlx5_ib_flow_prio *prio; |
| 932 | + struct mlx5_flow_spec *spec; |
| 933 | + |
| 934 | + spec = kcalloc(MAX_OPFC_RULES, sizeof(*spec), GFP_KERNEL); |
| 935 | + if (!spec) |
| 936 | + return -ENOMEM; |
| 937 | + |
| 938 | + switch (type) { |
| 939 | + case MLX5_IB_OPCOUNTER_CC_RX_CE_PKTS: |
| 940 | + if (set_ecn_ce_spec(dev, port_num, &spec[0], |
| 941 | + MLX5_FS_IPV4_VERSION) || |
| 942 | + set_ecn_ce_spec(dev, port_num, &spec[1], |
| 943 | + MLX5_FS_IPV6_VERSION)) { |
| 944 | + err = -EOPNOTSUPP; |
| 945 | + goto free; |
| 946 | + } |
| 947 | + spec_num = 2; |
| 948 | + fn_type = MLX5_FLOW_NAMESPACE_RDMA_RX_COUNTERS; |
| 949 | + priority = RDMA_RX_ECN_OPCOUNTER_PRIO; |
| 950 | + break; |
| 951 | + |
| 952 | + case MLX5_IB_OPCOUNTER_CC_RX_CNP_PKTS: |
| 953 | + if (!MLX5_CAP_FLOWTABLE(dev->mdev, |
| 954 | + ft_field_support_2_nic_receive_rdma.bth_opcode) || |
| 955 | + set_cnp_spec(dev, port_num, &spec[0])) { |
| 956 | + err = -EOPNOTSUPP; |
| 957 | + goto free; |
| 958 | + } |
| 959 | + spec_num = 1; |
| 960 | + fn_type = MLX5_FLOW_NAMESPACE_RDMA_RX_COUNTERS; |
| 961 | + priority = RDMA_RX_CNP_OPCOUNTER_PRIO; |
| 962 | + break; |
| 963 | + |
| 964 | + case MLX5_IB_OPCOUNTER_CC_TX_CNP_PKTS: |
| 965 | + if (!MLX5_CAP_FLOWTABLE(dev->mdev, |
| 966 | + ft_field_support_2_nic_transmit_rdma.bth_opcode) || |
| 967 | + set_cnp_spec(dev, port_num, &spec[0])) { |
| 968 | + err = -EOPNOTSUPP; |
| 969 | + goto free; |
| 970 | + } |
| 971 | + spec_num = 1; |
| 972 | + fn_type = MLX5_FLOW_NAMESPACE_RDMA_TX_COUNTERS; |
| 973 | + priority = RDMA_TX_CNP_OPCOUNTER_PRIO; |
| 974 | + break; |
| 975 | + |
| 976 | + default: |
| 977 | + err = -EOPNOTSUPP; |
| 978 | + goto free; |
| 979 | + } |
| 980 | + |
| 981 | + ns = mlx5_get_flow_namespace(dev->mdev, fn_type); |
| 982 | + if (!ns) { |
| 983 | + err = -EOPNOTSUPP; |
| 984 | + goto free; |
| 985 | + } |
| 986 | + |
| 987 | + prio = &dev->flow_db->opfcs[type]; |
| 988 | + if (!prio->flow_table) { |
| 989 | + prio = _get_prio(ns, prio, priority, |
| 990 | + dev->num_ports * MAX_OPFC_RULES, 1, 0); |
| 991 | + if (IS_ERR(prio)) { |
| 992 | + err = PTR_ERR(prio); |
| 993 | + goto free; |
| 994 | + } |
| 995 | + } |
| 996 | + |
| 997 | + dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; |
| 998 | + dst.counter_id = mlx5_fc_id(opfc->fc); |
| 999 | + |
| 1000 | + flow_act.action = |
| 1001 | + MLX5_FLOW_CONTEXT_ACTION_COUNT | MLX5_FLOW_CONTEXT_ACTION_ALLOW; |
| 1002 | + |
| 1003 | + for (i = 0; i < spec_num; i++) { |
| 1004 | + opfc->rule[i] = mlx5_add_flow_rules(prio->flow_table, &spec[i], |
| 1005 | + &flow_act, &dst, 1); |
| 1006 | + if (IS_ERR(opfc->rule[i])) { |
| 1007 | + err = PTR_ERR(opfc->rule[i]); |
| 1008 | + goto del_rules; |
| 1009 | + } |
| 1010 | + } |
| 1011 | + prio->refcount += spec_num; |
| 1012 | + kfree(spec); |
| 1013 | + |
| 1014 | + return 0; |
| 1015 | + |
| 1016 | +del_rules: |
| 1017 | + for (i -= 1; i >= 0; i--) |
| 1018 | + mlx5_del_flow_rules(opfc->rule[i]); |
| 1019 | + put_flow_table(dev, prio, false); |
| 1020 | +free: |
| 1021 | + kfree(spec); |
| 1022 | + return err; |
| 1023 | +} |
| 1024 | + |
| 1025 | +void mlx5_ib_fs_remove_op_fc(struct mlx5_ib_dev *dev, |
| 1026 | + struct mlx5_ib_op_fc *opfc, |
| 1027 | + enum mlx5_ib_optional_counter_type type) |
| 1028 | +{ |
| 1029 | + int i; |
| 1030 | + |
| 1031 | + for (i = 0; i < MAX_OPFC_RULES && opfc->rule[i]; i++) { |
| 1032 | + mlx5_del_flow_rules(opfc->rule[i]); |
| 1033 | + put_flow_table(dev, &dev->flow_db->opfcs[type], true); |
| 1034 | + } |
| 1035 | +} |
| 1036 | + |
850 | 1037 | static void set_underlay_qp(struct mlx5_ib_dev *dev,
|
851 | 1038 | struct mlx5_flow_spec *spec,
|
852 | 1039 | u32 underlay_qpn)
|
|
0 commit comments